Недавно я изучил следующую статью: Управление состоянием с помощью React Hooks - без Redux или Context API . С самого начала реакции наиболее обсуждаемым вопросом всегда является управление состоянием и глобальное состояние. Redux был популярным выбором, а в последнее время - контекстным API. Но этот подход кажется намного проще, меньше кода и более масштабируем.
Мой вопрос: может ли кто-нибудь увидеть обратную сторону использования такого подхода к управлению состоянием, который я, возможно, упустил из виду. Я немного изменил код для поддержки SSR, и он работает в Next js, а также сделал его немного более удобным для использования действий и настройки переменной состояния.
Вот код:
Codesandbox Demo
useGlobalState. js
import React, { useState, useEffect, useLayoutEffect } from 'react';
const effect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
function setState(newState) {
if (newState === this.state) return;
this.state = newState;
this.listeners.forEach((listener) => {
listener(this.state);
});
}
function useCustom() {
const newListener = useState()[1];
effect(() => {
this.listeners.push(newListener);
return () => {
this.listeners = this.listeners.filter((listener) => listener !== newListener);
};
}, []);
return [this.state, this.setState, this.actions];
}
function associateActions(store, actions) {
const associatedActions = {};
if (actions) {
Object.keys(actions).forEach((key) => {
if (typeof actions[key] === 'function') {
associatedActions[key] = actions[key].bind(null, store);
}
if (typeof actions[key] === 'object') {
associatedActions[key] = associateActions(store, actions[key]);
}
});
}
return associatedActions;
}
const useGlobalHook = (initialState, actions) => {
const store = { state: initialState, listeners: [] };
store.setState = setState.bind(store);
store.actions = associateActions(store, actions);
return useCustom.bind(store, React);
};
export default useGlobalHook;
Затем настроить пользовательский обработчик для переменной состояния может быть простой строкой или объектом вот простой:
import useGlobalState from './useGlobalState';
const initialState = 'Hi';
// Example action for complex processes setState will be passed to component for use as well
const someAction = (store, val) => store.setState(val);
const useValue = useGlobalState(initialState, { someAction });
export default useValue;
И использовать в компоненте:
import React from 'react'
import useVal from './useVal'
export default () => {
const [val, setVal, actions] = useVal();
const handleClick = () => {
setVal('New Val');
// or use some actions
actions.someAction('New Val');
}
return(
<div>{val}</div>
<button onClick={handleClick}>Click Me</button>
)
}
Все это кажется намного более чистым и простым подходом, и мне интересно, почему это не go подойти для государственного управления в React. Во-первых, вам не нужно все оборачивать в провайдере. Далее, это очень легко реализовать, и в фактическом приложении задействуется гораздо меньше кода. Может ли кто-нибудь увидеть обратную сторону такого подхода. Единственное, о чем я могу думать, это проблема повторного рендеринга, которая есть у context api, но небольшими частями это не должно быть проблемой.