Зачем снова делать колеса
крюк поставляется с ореолом колеса
Я не буду больше рассказывать о реагирующих хуках. Хуки предоставляют возможность абстрагировать состояние, что, естественно, заставляет людей думать об абстрагировании глобального состояния на основе хуков. Он рождается с ореолом колес, поэтому в сообществе есть много инструментов управления состоянием, основанных на хуках, например, тот, который недавно разработала команда Feibing.icestore, или этоstamen, но я предпочитаю этотunstated-next.
Тогда, если другие уже построили так много колес, зачем им еще нужно их строить? Естественно потому что:
Чужих колес не хватает
Напримерunstated-next, который по существу глобализует пользовательский хук. Идея очень хорошая, но, к сожалению, детализация слишком велика. Состояние, действия и эффекты должны поддерживаться в пользовательском хуке. Также более хлопотно добавлять useCallback и useMemo в ряд внутренних действий и эффектов.Если они извлекаются наружу, нужно передавать много параметров.Если написан TS, нужно написать много дженериков. Короче говоря, если проект относительно сложный, писать его будет более утомительно.
stamenНа самом деле неплохо. Объявите хранилище, содержащее состояние, редукторы и эффекты. И не нужно оборачивать Provider для компонента, можно подключать и отключать по желанию в разных местах, и реагировать на обновление. То есть я не очень люблю использовать диспетчеризацию, не так просто найти непосредственно объявление действия или эффекта, и теряется тип входного параметра и выходного параметра.
icestoreПроблема аналогичная. Говорят, что поддерживает TS, но на самом деле он неполный, после прочтения исходников типы полностью теряются. Кроме того, мне не очень нравится набор пространств имен.
Конечно, вышеуказанные проблемы также могут быть оптимизированы. Но зачем заморачиваться, там всего несколько строчек кода, а когда дело доходит до пиара людей, то колеса я уже сам написал. В общем, сделай сам.
мой идеальный тип
Так какого рода государственный инструмент управления я хочу? Перед Hoox я фактически реализовал версию, которая в основном скопировала версию API DVA (замените выход с async / a ждать). Вид как имин, но без пространства имен. Самая роковая и неразрешиваемая проблема - потерянные типы, потерянные ссылки на функцию.
Затем я подытожил то, что я действительно хочу:
- Глобальное управление состоянием, а не отдельный магазин;
- Действия и эффекты — это обычные функции, объявленные независимо и на которые ссылаются напрямую;
- Идеальная поддержка ТС.
Так что цель проста, так сказатьunstated-nextGo завернутая версия крючка. Итак, я реализовал версию, окончательные результаты таковы:
HooX
Создать глобальное состояние
// store.js
import createHoox from 'hooxjs'
// 声明全局初始状态
const state = {
count: 1
}
// 创建store
export const { setHoox, getHoox, useHoox } = createHoox(state)
// 创建一个 action
export const up = () => setHoox(({ count }) => ({ count: count + 1 }))
// 创建一个effect
export const effectUp = () => {
const [{ count }, setHoox] = getHoox();
const newState = { count: count + 1 }
return fetch('/api/up', newState).then(() => setHoox(newState))
// 或者直接引用action
// return fetch('/api/up', newState).then(up)
}
статус потребления
import { useHoox, up, effectUp } from './store';
function Counter() {
const [state] = useHoox()
return (
<div>
<div>{state.count}</div>
<button onClick={up}>up</button>
<button onClick={effectUp}>effectUp</button>
</div>
)
}
Изменить состояние напрямую
import { useHoox } from './store';
function Counter() {
const [state, setHoox] = useHoox()
return (
<div>
<div>{state.count}</div>
<input
value={state.count}
onChange={value => setHoox({ count: value })}
/
</div>
)
}
сбросить состояние
Мы знаем, что в компоненте класса черезthis.setState
заключается в выполнении слияния обновления состояния. Но в функциональном компонентеuseState
Второй параметр вернулсяsetState
Также делайте замену обновлений. В реальном использовании, на самом деле, у всех нас есть требования. Особенно проекты не ТС, модель статуса может быть динамической, скорее всего будет сброшена. Чтобы удовлетворить потребности всех, я также добавил API, чтобы было удобно для всех.
import { useHoox } from './store';
function Counter() {
const [state, setHoox, resetHoox] = useHoox()
return (
<div>
{state ? <div>{state.count}</div> : null}
<button onClick={() => resetHoox(null)>reset</button>
</div>
)
}
Глобальные вычисления
Фактически, с помощью вышеуказанного API мы также можем добиться чего-то похожего на vue.computed
Эффект.
import { useHoox } from './store';
export function useDoubleCount () {
const [{ count }] = useHoox();
return count * 2
}
Для некоторых очень сложных операций мы также можем использовать реакцииuseMemo
Займитесь оптимизацией.
import { useHoox } from './store';
export function usePowCount (number = 2) {
const [{ count }] = useHoox();
return useMemo(() => Math.pow(count, number), [count, number])
}
Кроме того, могут быть реализованы некоторые глобальные эффекты.
недостаточно хорошее место
Требуется провайдер
Нижний слой hoox основан наcontext
а такжеuseState
реализация, так как государство существуетcontext
Поэтому, как и в Redux, компоненты, потребляющие состояние, должны соответствоватьContext.Provider
Компоненты-потомки . Такие как:
import { Provider } from './store';
import Counter from './counter';
function App() {
return <Provider>
<Counter />
</Provider>
}
Это в свою очередь приводит к тому, что если компоненту нужно потреблять два хранилища, то его должно быть два.Provider
Компоненты-потомки .
hoox предоставляет синтаксический сахарcreateContainer
, синтаксис можно немного упростить.
import { createContainer } from './store';
import Counter from './counter';
function App () {
return <Counter />
}
export default createContainer(App)
другие плохие места
Оставь это в комментариях
Github
Конкретный исходный код и введение в API можно найти на github:GitHub.com/No Oh National Revival/Ооооооооо…
Я не буду подробно объяснять часть исходного кода, и там всего несколько строк кода, вы можете понять это, взглянув на него.