86

React の新しいフック機能を試していました。次の2つのコンポーネントがあることを考慮して(React Hooksを使用)-

const HookComponent = () => {
  const [username, setUsername] = useState('Abrar');
  const [count, setState] = useState();
  const handleChange = (e) => {
    setUsername(e.target.value);
  }

  return (
    <div>
      <input name="userName" value={username} onChange={handleChange}/>
      <p>{username}</p>
      <p>From HookComponent: {count}</p>
    </div>
  )
}


const HookComponent2 = () => {
  const [count, setCount] = useState(999);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

HookComponentフックは、コンポーネント間でステートフル ロジックを共有する問題を解決すると主張していますが、との間の状態は共有できないことがわかりましたHookComponent2。たとえば、 の変更は の変更をレンダリングcountHookComponent2ませんHookComponent

useState()フックを使用してコンポーネント間で状態を共有することは可能ですか?

4

7 に答える 7

49

外部状態管理ライブラリがなくても可能です。シンプルな観察可能な実装を使用するだけです:

function makeObservable(target) {
  let listeners = []; // initial listeners can be passed an an argument aswell
  let value = target;

  function get() {
    return value;
  }

  function set(newValue) {
    if (value === newValue) return;
    value = newValue;
    listeners.forEach((l) => l(value));
  }

  function subscribe(listenerFunc) {
    listeners.push(listenerFunc);
    return () => unsubscribe(listenerFunc); // will be used inside React.useEffect
  }

  function unsubscribe(listenerFunc) {
    listeners = listeners.filter((l) => l !== listenerFunc);
  }

  return {
    get,
    set,
    subscribe,
  };
}

subscribe次に、ストアを作成し、 inを使用して反応するようにフックしuseEffectます。

const userStore = makeObservable({ name: "user", count: 0 });

const useUser = () => {
  const [user, setUser] = React.useState(userStore.get());

  React.useEffect(() => {
    return userStore.subscribe(setUser);
  }, []);

  const actions = React.useMemo(() => {
    return {
      setName: (name) => userStore.set({ ...user, name }),
      incrementCount: () => userStore.set({ ...user, count: user.count + 1 }),
      decrementCount: () => userStore.set({ ...user, count: user.count - 1 }),
    }
  }, [user])

  return {
    state: user,
    actions
  }
}

そして、それはうまくいくはずです。React.Context状態を持ち上げる必要はありません

于 2020-05-25T12:03:43.030 に答える