Pull to refresh

Comments 8

Мы с коллегами тоже думали над хуками и разродились на библиотеку react-hoox, и как-то уже и стейты не нужны стали, и редакс. Все никак не доберемся написать на хабр статью подробную. Пока только readme.md закончили более-менее

Как только вышел новый Context-API (на самом деле уже достаточно старый) все ринулись писать и переводить статьи про то, как написать свой redux. На самом деле ни одно из решений не заменят redux, а просто переносит хранилище в глобальный контекст (что react позволял слепить и раньше, со старым контекстом). В отличие от redux, ваше решение работает синхронно, т.е. вызовет re-render компонента несколько раз, если dispatch() был вызван несколько раз подряд. Оно также не позволяет создать write-only компоненты или выбрать лишь часть стейта и игнорировать обновления остальных значений (см connect/useSelector()). И не видно ни слова про middleware.

В отличие от redux, ваше решение работает синхронно, т.е. вызовет re-render компонента несколько раз, если dispatch() был вызван несколько раз подряд

И давно уже React делает рендер синхронно?


Оно также не позволяет создать write-only компоненты

Что такое "write-only компоненты"? Чем компонент Button не подходит под это определение?


И не видно ни слова про middleware

А что не так с middleware?

И давно уже React делает рендер синхронно?

К сожаллению, за исклюючением обновления в рамках стандартных коллбеков — всегда.


Что такое «write-only компоненты»? Чем компонент Button не подходит под это определение?

Компоненты, которые не используют стейт, а только обновляю его. Кнопка вполне подходит под такое определение, например, кнопка инкремента счетчика. В предложенном решении она будет обновлена при каждом нажатии, хотя это ни к чему. С Redux при передаче константного mapStateToProps в connect() (или использования useDispatch()) можно избежать ненужного обновления.


const IncrementCounter = () => {
  const dispatch = useDispatch();

  // такой компонент не будет обновляться при каждом нажатии кнопки
  return (
    <Button onClick={ () => dispatch(increment()) }>Inc</Button>
  );
};

А что не так с middleware?

Предложенное решение их не поддерживает.

В предложенном решении она будет обновлена при каждом нажатии, хотя это ни к чему.

С чего бы?

Использование useContext() приведет к повторному вызову render-функции компонента-консьюмера при каждом изменении значения контекста. Не важно, изменился ли значения полей или нет.


<DadJokeContext.Provider value={{ state, actions }}>

Вот эта строка создает новое значение контекста при каждом рендере провайдера (пример на codesandbox)

А до следующего примера в статье вы не дочитали? Автор-то в итоге пришёл к вот такому варианту:


const actions = React.useMemo(() => ({
    fetchDadJoke,
}), [])

<DadJokeStateContext.Provider value={state}>
  <DadJokeActionsContext.Provider value={actions}>
    {children}
  </DadJokeActionsContext.Provider>
</DadJokeStateContext.Provider>

Виноват, с момент прочтения статьи до момента написания комментария видимо успел забыть про это. Хорошо, write-only компоненты с данным решением сделать можно. Тем не менее, все остальные более важные пункты все еще остаются актуальными и это все еще никакая не замена redux, а просто перенос глобального стейта в контекст, что можно было сделать и раньше (со старым context api) и хуки тут не при чем, это ровно так же работает без них.

Sign up to leave a comment.

Articles