gpt4 book ai didi

javascript - 为什么 `useContext` 不重新渲染我的组件?

转载 作者:行者123 更新时间:2023-11-28 16:51:59 24 4
gpt4 key购买 nike

根据 docs :

When the nearest <MyContext.Provider> above the component updates, this Hook will trigger a rerender with the latest context value passed to that MyContext provider. Even if an ancestor uses React.memo or shouldComponentUpdate, a rerender will still happen starting at the component itself using useContext. ... A component calling useContext will always re-render when the context value changes.

在我的 Gatsby JS 项目中,我这样定义我的上下文:

Context.js

import React from "react"

const defaultContextValue = {
data: {
filterBy: 'year',
isOptionClicked: false,
filterValue: ''
},
set: () => {},
}

const Context = React.createContext(defaultContextValue)

class ContextProviderComponent extends React.Component {
constructor() {
super()

this.setData = this.setData.bind(this)
this.state = {
...defaultContextValue,
set: this.setData,
}
}

setData(newData) {
this.setState(state => ({
data: {
...state.data,
...newData,
},
}))
}

render() {
return <Context.Provider value={this.state}>{this.props.children}</Context.Provider>
}
}

export { Context as default, ContextProviderComponent }

在包含多个组件的layout.js 文件中,我放置了上下文提供程序:

Layout.js:

import React from 'react'
import { ContextProviderComponent } from '../../context'

const Layout = ({children}) => {

return(
<React.Fragment>
<ContextProviderComponent>
{children}
</ContextProviderComponent>
</React.Fragment>
)
}

在我希望使用上下文的组件中:

import React, { useContext } from 'react'
import Context from '../../../context'

const Visuals = () => {

const filterByYear = 'year'
const filterByTheme = 'theme'

const value = useContext(Context)
const { filterBy, isOptionClicked, filterValue } = value.data

const data = <<returns some data from backend>>

const works = filterBy === filterByYear ?
data.nodes.filter(node => node.year === filterValue)
:
data.nodes.filter(node => node.category === filterValue)

return (
<Layout noFooter="true">
<Context.Consumer>
{({ data, set }) => (
<div onClick={() => set( { filterBy: 'theme' })}>
{ data.filterBy === filterByYear ? <h1>Year</h1> : <h1>Theme</h1> }
</div>
)
</Context.Consumer>
</Layout>
)

Context.Consumer工作正常,因为它成功更新并反射(reflect)了上下文的更改。然而,如代码中所示,我希望能够访问组件其他部分中更新的上下文值,即 return 之外的值。函数其中 Context.Consumer被专门使用。我假设使用 useContext hook 会对此有所帮助,因为每次单击 div 时,我的组件都会使用上下文中的新值重新渲染 - 但事实并非如此。任何帮助弄清楚为什么会出现这种情况的帮助将不胜感激。

TL;博士:<Context.Consumer>更新并反射(reflect)子组件 useContext 对上下文的更改尽管组件需要它,但不会。

更新:我现在发现useContext将从传递给 createContext 的默认上下文值中读取并且基本上将独立于 Context.Provider 运行。这就是这里发生的事情,Context.Provider包括修改状态的方法,而默认上下文值则不会。我现在的挑战是找出一种方法,将一个函数包含在默认上下文值中,该函数可以修改该值的其他属性。就目前情况而言:

const defaultContextValue = {
data: {
filterBy: 'year',
isOptionClicked: false,
filterValue: ''
},
set: () => {}
}

set是一个空函数,定义在ContextProviderComponent中(往上看)。我如何(如果可能)直接在上下文值中定义它,以便:

const defaultContextValue = {
data: {
filterBy: 'year',
isOptionClicked: false,
filterValue: ''
},
test: 'hi',
set: (newData) => {
//directly modify defaultContextValue.data with newData
}
}

最佳答案

您无需同时使用 <Context.Consumer>useContext钩。

通过使用useContext钩子(Hook)你可以访问存储在 Context 中的值。

关于您的具体示例,在 Visuals 组件中使用上下文的更好方法如下:

import React, { useContext } from "react";
import Context from "./context";

const Visuals = () => {
const filterByYear = "year";
const filterByTheme = "theme";

const { data, set } = useContext(Context);
const { filterBy, isOptionClicked, filterValue } = data;

const works =
filterBy === filterByYear
? "filter nodes by year"
: "filter nodes by theme";

return (
<div noFooter="true">
<div>
{data.filterBy === filterByYear ? <h1>Year</h1> : <h1>Theme</h1>}
the value for the 'works' variable is: {works}
<button onClick={() => set({ filterBy: "theme" })}>
Filter by theme
</button>
<button onClick={() => set({ filterBy: "year" })}>
Filter by year
</button>
</div>
</div>
);
};

export default Visuals;

此外,您似乎没有使用 works组件中的变量可能是您未获得所需结果的另一个原因。

您可以查看使用上述 useContext 实现的工作示例这与您在 sandbox 中的示例有些相似

希望这有帮助。

关于javascript - 为什么 `useContext` 不重新渲染我的组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59828215/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com