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