Pull to refresh

Comments 9

Была статья на схожую тему, где по другому было сделано, без пародии на redux — habr.com/ru/post/484952
Context там не используется, но можно сделать с использованием контекста.

Вместо
const removeTask = (taskForRemoving: Task) => {
        changeState({type: ActionType.REMOVE, payload: taskForRemoving})
    }

<button className='remove-button' onClick={()=>removeTask(task)}>X</button>

было бы
<button className='remove-button' onClick={()=>todoStore.removeTask(task)}>X</button>

Вместо редьюсера со switch был бы класс с функциями. А ActionType и ActionStringPayload были бы не нужны.

Я к тому, зачем разделять функцию на имя и тело функции (т.е. на action type и редьюсер)?

Еще замечу, что в примере из статьи, при любом изменении состояния, скорее всего будет перерисовка всех компонентов, начиная от компонента с контекстом, т.к. вложенные компоненты меняют его стейт.
Вообще, я бы не хранил состояние приложения в контексте. Оно может понадобится вне компонентов и тогда придется писать костыли.

А за упоминание Partial — спасибо! Не знал, что есть такое.

да, можно было бы писать на MobX и не думать о заведении констант с type, объектов с type и пэйлоадом, мутациях стора в иммутабельном формате, когда вместо изменения одних параметров приходится дублировать весь стор, кучи дополнительных ts-типов, иерархии проброса контекстов, лишних ререндерах. Так туду-листы уже не пишут

по поводу оптимизации — в реакте также добавлен HOC React.memo, с ним можно избежать лишнего перерендера — компоненты, не использующие useContext, не обновятся.

О доступе — контекст провайдер можно объявить в корне приложения — тогда чилдренами у него будут все (про проблему с оптимизацией уже сказал как можно решить с: )

Мне кажется, использование контекста с редьюсером — неплохая идея, если нужно реализовать какую-то логику, изолированную от общего приложения, например работу с формой.
Автору статьи спасибо, советую дополнить свой код обертками useCallback и вынесением экшенов в кастомные хуки:
const useAddTask = () => {
  const {changeState} = useContext(ContextApp)
  return (task) => changeState({type: ActionType.Add, payload: task})
}
О доступе — контекст провайдер можно объявить в корне приложения
Можно, но стоит ли слой глобальных данных объединять с view слоем? Как по мне, менее гибко. Часть бизнес-логики, которая должна использовать стор, придеться переносить в хуки/компоненты.
Recoil тоже так же сделали. А здесь issue о доступе к стору вне компонентов — github.com/facebookexperimental/Recoil/issues/410

Да и придумают вместо хуков что-то новое, как было в случае с миксинами и HOC, весь код написанный на хуках нельзя будет перенести в новый проект.
Люди разные. Кто-то мыслит существительными, кто-то глаголами. Уважаемый Дэн предлагает в основу положить действия, т.е. глагол. Мне лично переход от объектов к функциям кажется странным. В простейших случаях я использую функции, но сложные контролы предпочитаю строить на основе классов. Я не против функционального программирования, но для сложных форм больше подходит ООП
Вместо:
const App = () => {

    return (
        <>
            <NewTask />
            <TasksList />
        </>
    )
}

Гораздо чище было бы:
const App = () => (
  <>
    <NewTask />
    <TasksList />
  </>
);

А в целом для этих целей настроили Prettier в проекте и забыли. Раньше постоянно одних раздражал грязно отформатированный код, а других — что их постоянно ругали за это.
На вкус и цвет…
Мне в этом чистом варианте не нравится, что компоненты только с JSX и компоненты с логикой имеют разное форматирование. А при добавлении одной строчки логики, добавляются return и { }.
Оно, конечно, так. Но для этого и существует укроченный и не укороченный синтаксис в языке, Реакт здесь вообще сбоку.
const sum = (a, b) => {
  return a + b;
}

Или так:
const sum = (a, b) => a + b

В общем это действительно личные предпочтения. Но я не стану отказываться от сахара, ради того, чтобы всё выглядело одинаково.
Sign up to leave a comment.

Articles