Можно ли совместно использовать состояния между компонентами, используя хук useState() в React?

Я экспериментировал с новой функцией Hook в React. Учитывая, что у меня есть следующие два компонента (с использованием 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 не являются доступными. Например, изменение count в HookComponent2 не приводит к изменению HookComponent.

Можно ли делиться состояниями между компонентами с помощью useState() hook?

Ответ 1

Если вы ссылаетесь на состояние компонента, то хуки не помогут вам разделить его между компонентами. Состояние компонента является локальным для компонента. Если ваше состояние живет в контексте, то хук useContext будет полезен.

По сути, я думаю, что вы неправильно поняли строку "разделение логики состояния между компонентами". Состояние логики отличается от состояния. Логика состояния - это то, что вы делаете, что изменяет состояние. Например, компонент подписывается на хранилище в componentDidMount() и отменяет подписку в componentWillUnmount(). Такое поведение подписки/отписки может быть реализовано в ловушке, и компоненты, которые нуждаются в этом поведении, могут просто использовать ловушку.

Если вы хотите поделиться состоянием между компонентами, есть несколько способов сделать это, каждый со своими достоинствами:

1. Поднимите состояние вверх

Поднимите состояние до общего предка двух компонентов.

function Ancestor() {
    const [count, setCount] = useState(999);
    return <>
      <DescendantA count={count} />
      <DescendantB count={count} />
    </>;
  }

Этот подход к совместному использованию состояний принципиально не отличается от традиционного способа использования состояния, хуки просто дают нам другой способ объявления состояния компонента.

2. Контекст

Если потомки находятся слишком глубоко в иерархии компонентов, и вы не хотите передавать состояние слишком многим слоям, вы можете использовать Context API.

Есть хук useContext который вы можете использовать в дочерних компонентах.

3. Решение по управлению внешним государством

Государственные библиотеки управления, такие как Redux или Mobx. После этого ваш штат будет находиться в магазине за пределами React, и компоненты смогут подключаться/подписываться на магазин для получения обновлений.

Ответ 2

в документе говорится:

Мы импортируем UseState Hook из React. Это позволяет сохранить локальное состояние в функциональном компоненте.

он не упоминает, что состояние может быть разделено между компонентами, useState hook просто дает вам более быстрый способ объявить поле состояния и его корреспондентский сеттер в одной команде.

Ответ 3

Вам все равно нужно поднять ваше состояние до компонента-предка HookComponent1 и HookComponent2. Это то, как вы делите состояние раньше, и последний хук api ничего не меняет.

Ответ 4

С крючками это не возможно напрямую. Я рекомендую вам взглянуть на реакцию легко-состояние. https://github.com/solkimicreb/react-easy-state

Я использую его в больших приложениях, и он работает как шарм.

Ответ 5

Я создал сумасшедший, который позволяет вам делать именно это - https://github.com/pie6k/hooksy

import { createStore } from 'hooksy';

interface UserData {
  username: string;
}

const defaultUser: UserData = { username: 'Foo' };

export const [useUserStore] = createStore(defaultUser); // we've created store with initial value.
// useUserStore has the same signature like react useState hook, but the state will be shared across all components using it