React中嵌套组件更新Context失效:函数传递失败问题
React Context API 传递函数失败的解决方案
嘿,我来帮你搞定这个Context传函数的问题!你的代码里有两个小问题导致函数没法正常工作,咱们一步步来修正:
问题1:没必要把函数存在state里
你把toggleTheme函数放进了组件的state中,但state是用来存储组件状态数据的,方法类的逻辑完全没必要存在这里。而且这样传递this.state作为Provider的value,其实是多此一举,还可能引发不必要的状态更新。
问题2:没有触发函数的交互元素
你的Def组件接收了onClick props,但组件里没有任何可点击的元素(比如按钮)来调用这个函数,所以就算函数传过去了,也没机会执行~
修改后的完整代码
import React from 'react'; // 创建Context,默认值可以保留,方便没有Provider时的降级处理 const ThemeContext = React.createContext({ theme: 'light', toggleTheme: () => {} }) class MouseTracker2 extends React.Component { constructor(props) { super(props); this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === 'dark' ? 'light' : 'dark', })); }; // state只存主题状态,去掉不必要的函数存储 this.state = { theme: 'dark' } } render() { // Provider直接传递theme状态和toggleTheme方法 return ( <div> <ThemeContext.Provider value={{ theme: this.state.theme, toggleTheme: this.toggleTheme }}> <Abc /> </ThemeContext.Provider> </div> ) } } class Abc extends React.Component { render() { return ( <div> <ThemeContext.Consumer> {({theme,toggleTheme}) => <Def theme={theme} onClick={toggleTheme} />} </ThemeContext.Consumer> </div> ) } } class Def extends React.Component { render() { return ( <div> <p>efgh</p> <div>当前主题:{this.props.theme}</div> {/* 添加按钮来触发toggleTheme函数 */} <button onClick={this.props.onClick}>切换主题</button> </div> ) } } export default MouseTracker2
额外优化:用Hook简化代码(React 16.8+)
如果你的项目支持React Hooks,可以把类组件改成函数组件,代码会简洁很多:
import React, { useContext, useState } from 'react'; const ThemeContext = React.createContext({ theme: 'light', toggleTheme: () => {} }) const MouseTracker2 = () => { const [theme, setTheme] = useState('dark'); const toggleTheme = () => { setTheme(prevTheme => prevTheme === 'dark' ? 'light' : 'dark'); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> <Abc /> </ThemeContext.Provider> ); }; const Abc = () => { const { theme, toggleTheme } = useContext(ThemeContext); return <Def theme={theme} onClick={toggleTheme} />; }; const Def = ({ theme, onClick }) => { return ( <div> <p>efgh</p> <div>当前主题:{theme}</div> <button onClick={onClick}>切换主题</button> </div> ); }; export default MouseTracker2
这样修改后,你点击按钮就能正常切换主题啦~
内容的提问来源于stack exchange,提问作者Kiran
相关产品推荐
相关产品推荐

