Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React不会在自定义挂钩中的状态更新时重新呈现所有组件_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript React不会在自定义挂钩中的状态更新时重新呈现所有组件

Javascript React不会在自定义挂钩中的状态更新时重新呈现所有组件,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我已经创建了两个组件C1和C2以及一个自定义钩子计数器 C1显示useCounter挂钩的计数属性 C2显示计数属性,并在单击按钮时增加或减少计数属性 当前行为:更改计数时,更新的值仅显示在C2中,而不显示在C1中 预期行为:两个组件应在计数更新时重新呈现 如果我遗漏了什么,请告诉我 PS:我已经使用上下文API和redux完成了这项工作。只是想知道是否可以使用自定义挂钩实现相同的行为: 代码沙盒链接: 您可能希望使用上下文API共享同一个实例,因为自定义钩子useCounter将为装载时计数分

我已经创建了两个组件C1和C2以及一个自定义钩子计数器

C1显示useCounter挂钩的计数属性

C2显示计数属性,并在单击按钮时增加或减少计数属性

当前行为:更改计数时,更新的值仅显示在C2中,而不显示在C1中

预期行为:两个组件应在计数更新时重新呈现

如果我遗漏了什么,请告诉我

PS:我已经使用上下文API和redux完成了这项工作。只是想知道是否可以使用自定义挂钩实现相同的行为:

代码沙盒链接:


您可能希望使用上下文API共享同一个实例,因为自定义钩子useCounter将为装载时计数分配一个新实例:

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>
  );
}

您可能希望使用上下文API共享同一个实例,因为自定义钩子useCounter将为装载时计数分配一个新实例:

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>
  );
}
使用相同钩子的两个组件是否共享状态?不是。自定义钩子是一种重用有状态逻辑的机制,例如设置订阅和记住当前值,但是每次使用自定义钩子时,其中的所有状态和效果都是完全隔离的

请参阅中的第3点

它们不是一种共享状态的方式,而是一种共享状态逻辑的方式。我们不想破坏自上而下的数据流

参考:

使用相同钩子的两个组件是否共享状态?不是。自定义钩子是一种重用有状态逻辑的机制,例如设置订阅和记住当前值,但是每次使用自定义钩子时,其中的所有状态和效果都是完全隔离的

请参阅中的第3点

它们不是一种共享状态的方式,而是一种共享状态逻辑的方式。我们不想破坏自上而下的数据流


参考资料:

嘿,我完全同意@RVRJ的解释。那么,当您导入任何钩子时会发生什么呢?它将创建该钩子的新对象。假设您在两个不同的文件中导入相同的钩子,这意味着您正在创建该钩子的两个不同对象

在这里,我尝试只使用钩子来解决您的问题,但我只导入钩子一次,并将其对象传递给子组件和

下面是我如何创建useCounter钩子的单个对象的示例

现在你可以在每个孩子身上访问count和updateCount作为道具

这是更换后的C1部件

这是你的指挥控制系统

以下是您问题的最新有效解决方案


注意:我不知道为相同的状态值使用钩子的用例是什么,所以我仍然建议您应该使用redux在组件之间共享状态。

嘿,我完全同意@RVRJ的解释。那么,当您导入任何钩子时会发生什么呢?它将创建该钩子的新对象。假设您在两个不同的文件中导入相同的钩子,这意味着您正在创建该钩子的两个不同对象

在这里,我尝试只使用钩子来解决您的问题,但我只导入钩子一次,并将其对象传递给子组件和

下面是我如何创建useCounter钩子的单个对象的示例

现在你可以在每个孩子身上访问count和updateCount作为道具

这是更换后的C1部件

这是你的指挥控制系统

以下是您问题的最新有效解决方案


注意:我不知道对相同的状态值使用钩子的用例是什么,所以我仍然建议您应该使用redux在组件之间共享状态。

除非您将它们包装在使用自定义钩子的父容器中,否则它们不会共享状态。如果您希望它们共享状态,则将自定义钩子设置为上下文。钩子只是函数。它们没有共享状态,就像函数的状态不会在调用之间共享一样。例如,如果一个钩子共享了它的状态,那么你只能使用useState钩子一次,因为该状态对象将在整个应用程序中共享。那没有道理。钩子是实例。每次调用一个实例时,它都是一个新实例。除非将它们包装在使用自定义挂钩的父容器中,否则它们不会共享状态。如果希望它们共享状态,则将自定义挂钩设置为上下文。钩子只是函数。它们没有共享状态,就像函数的状态不会在调用之间共享一样。例如,如果一个钩子共享了它的状态,那么你只能使用useState钩子一次,因为该状态对象将在整个应用程序中共享。那没有道理。钩子是实例。每次你调用一个实例,它都是一个新实例。嗨,丹尼斯,谢谢你的回复:但正如我提到的,我已经通过上下文和redux实现了这个行为。我只是想用钩子来实现这一点。哦,所以你必须把状态提升到最近的通用父应用程序,才能使它只在c上运行
是的,这会起作用,但我希望直接共享和上下文或redux相同的状态。同样在官方文档中,他们在两个组件中使用了状态。查看更新的答案,react中没有这样的内置API,但您可以使用库或使用上下文自己编写。嗨,Dennis,感谢您的回答:但正如我提到的,我已经使用上下文和redux实现了这种行为。我只是想用钩子来实现这一点。哦,所以你必须将状态提升到最近的公共父应用程序,以便使其仅在自定义钩子上工作。是的,这将起作用,但我希望直接共享与上下文或redux相同的状态。同样在官方文档中,他们在两个组件中使用了状态。查看更新的答案,react中没有这样的内置API,但是您可以使用库或使用上下文自己编写。
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
}
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;
// 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 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;