children useContext() 未使用当前值重新呈现
children with useContext() not rerendered with current value
我查看了所有标题相似的帖子,但没有找到任何可以帮助我理解和解决问题的帖子。
我已经创建了一个传递开关状态(切换或不切换)的上下文。问题是消费者 (children) 没有收到更改的上下文值(通过状态设置)。它是一个主值,一个布尔值,而不是 object 或数组,因此不需要重建。我不知道我做错了什么。
const Price = ({ showYearlyPrice }) => {
function getPriceParts(showYearlyPrice: boolean){
return showYearlyPrice ? "a" : "b";
}
const mainPrice = getPriceParts(showYearlyPrice);
return (
<>
<div className="flex flex-row">
<p className="text-grey text-sm">
{mainPrice}
</p>
</>
);
};
const PricingHeader = ({
price,
}) => {
// Subscribe to switch event
const isToggled = useContext(SwitchContext);
console.log(isToggled)// Only prints once, with default value every time
return (
<SubscribableSwitch color={sectionBackground}>
<Section bg={sectionBackground} spacing={SectionSpacing.BOTTOM_ONLY}>
<Price showYearlyPrice={isToggled as boolean} price={price}/>
</Section>
</SubscribableSwitch>
);
};
export default PricingHeader;
然后是实际的 SubscribableSwitch 组件,其中的切换效果很好,并接收更新的上下文值。
export const SwitchContext = createContext(false); // Default value, if I put "potato" that's what gets printed in children
const Toggle = ({ toggle }) => {
const isToggled = useContext(SwitchContext);
return (
<div className="flex justify-center mb-8 mt-2">
<h2 onClick={toggle}>click me</h2>
{!isToggled && (
<span>
Not toggled
</span>
)}
</div>
);
};
const SubscribableSwitch = ({color, children}) => {
const [isToggled, setToggle] = useState(false);
const toggle = () => setToggle((value) => !value);
return (
<SwitchContext.Provider value={isToggled}>
<Toggle toggle={toggle}/>
{children} // Where children is PricingHeader
</SwitchContext.Provider>
);
};
export default SubscribableSwitch;
我想通了,我觉得自己很蠢。
useContext 必须在 child 中使用。 A quote:
useContext(MyContext) only lets you read the context and subscribe to
its changes. You still need a <MyContext.Provider> above in the tree
to provide the value for this context.
我出错的确切位置是在打印 SubscribableSwitch 的组件的渲染函数中调用 useContext。代码应该是这样的:
const Price = () => {
function getPriceParts(showYearlyPrice: boolean){
return showYearlyPrice ? "a" : "b";
}
const isToggled = useContext(SwitchContext);
const mainPrice = getPriceParts(isToggled);
return (
<>
<div className="flex flex-row">
<p className="text-grey text-sm">
{mainPrice}
</p>
</>
);
};
const PricingHeader = ({
price,
}) => {
//useContext should NOT be here, I'm not a child of the Context Provider
return (
<SubscribableSwitch color={sectionBackground}>
<Section bg={sectionBackground} spacing={SectionSpacing.BOTTOM_ONLY}>
<Price price={price}/>
</Section>
</SubscribableSwitch>
);
};
导出默认 PricingHeader;
我查看了所有标题相似的帖子,但没有找到任何可以帮助我理解和解决问题的帖子。
我已经创建了一个传递开关状态(切换或不切换)的上下文。问题是消费者 (children) 没有收到更改的上下文值(通过状态设置)。它是一个主值,一个布尔值,而不是 object 或数组,因此不需要重建。我不知道我做错了什么。
const Price = ({ showYearlyPrice }) => {
function getPriceParts(showYearlyPrice: boolean){
return showYearlyPrice ? "a" : "b";
}
const mainPrice = getPriceParts(showYearlyPrice);
return (
<>
<div className="flex flex-row">
<p className="text-grey text-sm">
{mainPrice}
</p>
</>
);
};
const PricingHeader = ({
price,
}) => {
// Subscribe to switch event
const isToggled = useContext(SwitchContext);
console.log(isToggled)// Only prints once, with default value every time
return (
<SubscribableSwitch color={sectionBackground}>
<Section bg={sectionBackground} spacing={SectionSpacing.BOTTOM_ONLY}>
<Price showYearlyPrice={isToggled as boolean} price={price}/>
</Section>
</SubscribableSwitch>
);
};
export default PricingHeader;
然后是实际的 SubscribableSwitch 组件,其中的切换效果很好,并接收更新的上下文值。
export const SwitchContext = createContext(false); // Default value, if I put "potato" that's what gets printed in children
const Toggle = ({ toggle }) => {
const isToggled = useContext(SwitchContext);
return (
<div className="flex justify-center mb-8 mt-2">
<h2 onClick={toggle}>click me</h2>
{!isToggled && (
<span>
Not toggled
</span>
)}
</div>
);
};
const SubscribableSwitch = ({color, children}) => {
const [isToggled, setToggle] = useState(false);
const toggle = () => setToggle((value) => !value);
return (
<SwitchContext.Provider value={isToggled}>
<Toggle toggle={toggle}/>
{children} // Where children is PricingHeader
</SwitchContext.Provider>
);
};
export default SubscribableSwitch;
我想通了,我觉得自己很蠢。
useContext 必须在 child 中使用。 A quote:
useContext(MyContext) only lets you read the context and subscribe to its changes. You still need a <MyContext.Provider> above in the tree to provide the value for this context.
我出错的确切位置是在打印 SubscribableSwitch 的组件的渲染函数中调用 useContext。代码应该是这样的:
const Price = () => {
function getPriceParts(showYearlyPrice: boolean){
return showYearlyPrice ? "a" : "b";
}
const isToggled = useContext(SwitchContext);
const mainPrice = getPriceParts(isToggled);
return (
<>
<div className="flex flex-row">
<p className="text-grey text-sm">
{mainPrice}
</p>
</>
);
};
const PricingHeader = ({
price,
}) => {
//useContext should NOT be here, I'm not a child of the Context Provider
return (
<SubscribableSwitch color={sectionBackground}>
<Section bg={sectionBackground} spacing={SectionSpacing.BOTTOM_ONLY}>
<Price price={price}/>
</Section>
</SubscribableSwitch>
);
};
导出默认 PricingHeader;