自定义挂钩,同步更新所有使用它的组件
Custom hook that updates all components that use it in sync
我正在尝试在使用自定义挂钩的 React 中创建一个 Switch 组件。我希望其他组件使用相同的自定义挂钩,以便在单击 Switch 时更新它们。为此,我创建了这个自定义挂钩:
function useToggle() {
const [isToggled, setIsToggled] = useState(false);
const toggle = React.useCallback(
() => setIsToggled(state => !state),
[setIsToggled],
);
return [isToggled, toggle];
}
然后在我想订阅这个自定义挂钩的 Switch 组件中:
const Switch = () => {
const [isToggled, toggle] = useToggle();
return (
<Switch
onChange={toggle as any}
checked={isToggled as boolean}
...
/>
);
}
然后在根据开关是否切换而改变值的组件中,我有:
const PricingHeader = () => {
// Subscribe to switch's event
const [isToggled, toggle] = useToggle();
return (<Price showSpecialPrice={isToggled} />);
}
有问题吗?组件 独立更新 。我可以单击 switch,我看到它在切换时呈现不同的值,但我没有看到 Price 在切换时显示不同的价格被切换。 价格在我点击开关时完全不受影响。
不确定我做错了什么?我想象每次使用 useToggle 时返回的 isToggled 状态都是不同的。我正在尝试做的事情是否可行?
有可能,您可以通过 Context API:
分享您的 toggle
状态
const SwitchContext = createContext();
function useToggle() {
return useContext(SwitchContext);
}
const Switch = () => {
const [isToggled, toggle] = useToggle();
return <button onClick={toggle}>{isToggled ? "ON" : "OFF"}</button>;
};
const Price = () => {
const [isToggled] = useToggle();
return <>The price {isToggled ? "IS TOGGLED" : "IS NOT TOGGLED"}</>;
};
export default function App() {
const [isToggled, toggle] = useReducer((p) => !p, false);
return (
<SwitchContext.Provider value={[isToggled, toggle]}>
<Switch />
<Price />
</SwitchContext.Provider>
);
}
我可能建议您为此使用 React Context。您可以使用 createContext
创建一个 ToggleContext
并将其与 useContext
-
一起使用
const { createContext, useContext, useState } = React
const ToggleContext = createContext(false)
function useToggle (initialState) {
const [isToggle, setToggle] = useState(initialState)
const toggle = () => setToggle(value => !value)
return [isToggle, toggle]
}
function MyApp () {
const [isToggle, toggle] = useToggle(false)
return (
<ToggleContext.Provider value={isToggle}>
<p>Click any switch</p>
<Switch onClick={toggle} />
<Switch onClick={toggle} />
<Switch onClick={toggle} />
</ToggleContext.Provider>
)
}
function Switch ({ onClick }) {
const isToggle = useContext(ToggleContext)
return <input type="checkbox" onClick={onClick} checked={isToggle} />
}
ReactDOM.render(<MyApp />, document.querySelector("main"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<main></main>
我正在尝试在使用自定义挂钩的 React 中创建一个 Switch 组件。我希望其他组件使用相同的自定义挂钩,以便在单击 Switch 时更新它们。为此,我创建了这个自定义挂钩:
function useToggle() {
const [isToggled, setIsToggled] = useState(false);
const toggle = React.useCallback(
() => setIsToggled(state => !state),
[setIsToggled],
);
return [isToggled, toggle];
}
然后在我想订阅这个自定义挂钩的 Switch 组件中:
const Switch = () => {
const [isToggled, toggle] = useToggle();
return (
<Switch
onChange={toggle as any}
checked={isToggled as boolean}
...
/>
);
}
然后在根据开关是否切换而改变值的组件中,我有:
const PricingHeader = () => {
// Subscribe to switch's event
const [isToggled, toggle] = useToggle();
return (<Price showSpecialPrice={isToggled} />);
}
有问题吗?组件 独立更新 。我可以单击 switch,我看到它在切换时呈现不同的值,但我没有看到 Price 在切换时显示不同的价格被切换。 价格在我点击开关时完全不受影响。
不确定我做错了什么?我想象每次使用 useToggle 时返回的 isToggled 状态都是不同的。我正在尝试做的事情是否可行?
有可能,您可以通过 Context API:
分享您的toggle
状态
const SwitchContext = createContext();
function useToggle() {
return useContext(SwitchContext);
}
const Switch = () => {
const [isToggled, toggle] = useToggle();
return <button onClick={toggle}>{isToggled ? "ON" : "OFF"}</button>;
};
const Price = () => {
const [isToggled] = useToggle();
return <>The price {isToggled ? "IS TOGGLED" : "IS NOT TOGGLED"}</>;
};
export default function App() {
const [isToggled, toggle] = useReducer((p) => !p, false);
return (
<SwitchContext.Provider value={[isToggled, toggle]}>
<Switch />
<Price />
</SwitchContext.Provider>
);
}
我可能建议您为此使用 React Context。您可以使用 createContext
创建一个 ToggleContext
并将其与 useContext
-
const { createContext, useContext, useState } = React
const ToggleContext = createContext(false)
function useToggle (initialState) {
const [isToggle, setToggle] = useState(initialState)
const toggle = () => setToggle(value => !value)
return [isToggle, toggle]
}
function MyApp () {
const [isToggle, toggle] = useToggle(false)
return (
<ToggleContext.Provider value={isToggle}>
<p>Click any switch</p>
<Switch onClick={toggle} />
<Switch onClick={toggle} />
<Switch onClick={toggle} />
</ToggleContext.Provider>
)
}
function Switch ({ onClick }) {
const isToggle = useContext(ToggleContext)
return <input type="checkbox" onClick={onClick} checked={isToggle} />
}
ReactDOM.render(<MyApp />, document.querySelector("main"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<main></main>