React не перерисовывает все компоненты при обновлении состояния в пользовательском хуке - PullRequest
1 голос
/ 17 марта 2020

Я создал 2 компонента C1 и C2 и один custom hook useCounter.

C1 отображает "count" свойство useCounter hook.

C2 отображает "count" свойство, а также увеличивает или уменьшает его при нажатии кнопки.

Current behavior: При изменении "count" обновленное значение отображается только в C2, а не в C1.

Expected behavior: При обновлении "count" оба компонента должны re-render.

Пожалуйста, дайте мне знать, если я что-то упустил.

PS: I ' мы уже сделали это, используя Context API и redux. Просто хочу узнать, можно ли добиться такого же поведения, используя custom hooks:)

Codesandbox link: Демонстрация пользовательских хуков

import { useState } from "react";

function useCounter() {
  const [count, setCount] = useState(0);
  const updateCounter = newVal => {
    setCount(newVal);
  };

  //return [count, useCallback( (newVal) => setCount(newVal))];
  return [count, updateCounter];
}
export default useCounter;

Ответы [ 3 ]

2 голосов
/ 17 марта 2020

Возможно, вы захотите использовать Context API для совместного использования того же экземпляра, так как пользовательский хук useCounter назначит новый экземпляр count при монтировании:

export const CounterContext = React.createContext();

function App() {
  const counterController = useCounter();
  return (
    <CounterContext.Provider value={counterController}>
      <div className="App">
        <h1>App Component</h1>
        <hr />
        <C1 />
        <hr />
        <C2 />
      </div>
    </CounterContext.Provider>
  );
}

// Use context
function C1() {
  const [count] = useContext(CounterContext);
  return (
    <div>
      Component 1 <br />
      Count: {count}
    </div>
  );
}

Edit nostalgic-hypatia-by6s4


Кроме того, вы можете использовать такую ​​библиотеку, как reusable:

const useCounter = createStore(() => {
  const [counter, setCounter] = useState(0);

  return {
    counter,
    increment: () => setCounter(prev => prev + 1)
  }
});

const Comp1 = () => {
  const something = useCounter();
}

const Comp2 = () => {
  const something = useCounter(); // same something
}
1 голос
/ 17 марта 2020

Эй, я полностью согласен с объяснениями @ RVRJ. Итак, что произойдет, когда вы импортируете какие-либо хуки, это создаст новый объект этого хука. Давайте предположим, что если вы импортируете один и тот же хук в два разных файла, это означает, что вы создаете два разностных объекта этого хука.

Здесь я попытался решить вашу проблему, используя только хуки, но я импортирую хук только один раз и прошел его объект к дочернему компоненту <C1 /> and <C2 />.

Вот пример того, как я создал отдельный объект useCounter hook

import React from "react";
import C1 from "./components/C1";
import C2 from "./components/C2";
import useCounter from "./hooks/useCounter";

function App() {
  const [count, updateCount] = useCounter(); // <<-- created one object

  return (
    <div className="App">
      <h1>App Component</h1>
      <hr />
      <C1 count={count} updateCount={updateCount} /> {/* passing values ad props */}
      <hr />
      <C2 count={count} updateCount={updateCount} /> {/* passing values ad props */}
    </div>
  );
}

export default App;

, и теперь вы можете получить доступ к count и updateCount как реквизиты у каждого ребенка.

Вот компонент C1 после изменения

// C1 component

 import React from "react";

 function C1({ count }) { {/* <-- access count as props */}
   return (
     <div>
       Component 1 <br />
       Count: {count}
     </div>
   );
 }
 export default C1;

А вот ваш компонент C2

// C2 component
import React from "react";

function C3({ count, updateCount }) { {/* <-- access count and as updateCount props */}
  const handleIncr = () => {
    updateCount(count + 1);
  };
  const handleDecr = () => {
    updateCount(count - 1);
  };
  return (
    <div>
      Component 2 <br />
      <button onClick={handleIncr}>Increment</button>
      <button onClick={handleDecr}>Decrement</button>
      <br />
      <br />
      <br />
      Count: {count}
    </div>
  );
}
export default C3;

Вот обновленные и рабочие решения вашей проблемы https://codesandbox.io/s/romantic-fire-b3exw

Примечание: я не знаю, каков вариант использования хуков для тех же значений состояния, поэтому я все же рекомендую вам используйте redux для совместного использования состояний между компонентами.

0 голосов
/ 17 марта 2020

Есть ли два компонента, использующие одно и то же состояние общего ресурса хуков? Нет. Пользовательские хуки - это механизм многократного использования логических состояний c (например, настройка подписки и запоминание текущего значения), но каждый раз, когда вы используете пользовательский хук, все его состояние и эффекты полностью изолированы.

См. пункт # 3 в Использование пользовательского хука


Это не способ делиться состоянием, а способ делиться логикой с состоянием c. Мы не хотим нарушать нисходящий поток данных!

Ссылка: Определение смысла реагирующих хуков

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...