上下文提供程序未触发 this.props.children 的重新渲染
Posted
技术标签:
【中文标题】上下文提供程序未触发 this.props.children 的重新渲染【英文标题】:Context Provider not triggering re-render of this.props.children 【发布时间】:2019-10-30 13:46:27 【问题描述】:我使用上下文提供程序 (AccountProvider.js) 作为向其所有子组件提供帐户详细信息(以及通过 socket.io 连接的通知)的一种方式。通知和用户对象可以很好地加载到 AccountProvider 组件中,并且实际上会不断更新自己的状态。
知道如果父组件的状态发生变化,这应该意味着父组件的子组件也应该重新渲染吧?显然这里不是这样,我似乎无法弄清楚为什么。
这个问题有什么解决办法吗?也许需要强制更新子组件?
AccountProvider.js
import React, Component from 'react'
import axios from 'axios'
import socketIOClient from "socket.io-client";
import config from '../config/config'
export const myContext = React.createContext();
export default class AccountProvider extends Component
state =
data: []
async componentDidMount()
const auth_token = localStorage.getItem('jwt token')
const header = 'Bearer ' + auth_token;
const res = await axios.get(config.API_URL+'/api/account', headers: Authorization:header);
const blob = await axios.get(config.API_URL+'/' + res.data.image, headers: Authorization:header, responseType: "blob");
var user = res.data;
user["image"] = URL.createObjectURL(blob.data);
this.setState(
data: user
);
const io = socketIOClient(config.REDIS_URL, query: jwt: localStorage.getItem('jwt token') );
io.on("event", data =>
if (data !== this.state.notifications)
var curr_data = this.state.data;
curr_data["notifications"] = data;
this.setState(data: curr_data);
);
io.on("reconnect", () =>
io.emit("jwt", localStorage.getItem('jwt token'));
)
render()
return (
<myContext.Provider value=this.state.data>
this.props.children
</myContext.Provider>
)
App.js(渲染)
<AccountProvider>
<Route
path="/dashboard"
render=( match: url ) => (
<Dashboard>
<Switch>
<Route path=`$url/Account` component=Account exact />
<Route path=`$url/Deposits` component=Deposits exact />
<Route path=`$url/Notifications` component=Client exact />
<Route path=`$url/` component=Account exact /> */
<Route component=Page404Dashboard />
</Switch>
</Dashboard>
)/>
</AccountProvider>
Dashboard.js
import React, Component from 'react'
import AccountContent from './AccountContent';
import PendingCard from '../PendingCard';
import myContext from '../../../AccountProvider'
class Dashboard extends Component
render()
// The following should log notifications after AccountProvider rerenders
console.log(this.context.notifications && this.context.notifications);
return (
<>
this.props.hasCard ? <AccountContent/> : <PendingCard/>
</>
)
Dashboard.contextType = myContext;
export default Dashboard;
【问题讨论】:
"这应该意味着父组件的子组件也都应该重新渲染吧?"没有。 Does new React Context API trigger re-renders?的可能重复 【参考方案1】:改变:
var curr_data = this.state.data;
curr_data["notifications"] = data;
this.setState(data: curr_data);
与:
var curr_data = Object.assign(, this.state.data);
curr_data["notifications"] = data;
this.setState(data: curr_data);
你并没有真正用第一种情况更新状态
【讨论】:
这行得通,我很好奇为什么第一个案例没有更新状态 太棒了!它不起作用,因为你得到了 curr_data 然后改变它......但是 curr_data 和 data 是同一个对象......所以当你 setState “数据”没有改变......所以没有新的渲染跨度>以上是关于上下文提供程序未触发 this.props.children 的重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
React Context + Firebase Auth 未填充 onAuthStateChanged
Next.js 上下文提供程序用页面特定布局组件包装 App 组件,提供未定义的数据
在上下文之间传递 objectID 时未触发 to-many 错误