试图学习如何使用反应钩子。我使用createContext,我想将状态和函数一起转移到其他组件,但我需要有关如何执行此操作的帮助。我还想问一下这样做是否有意义。
事实上,在我的情况下,我可以通过使用setState来更新状态,但是通过在上下文中定义一个函数,我认为在任何地方使用此函数更有意义。我错了吗?
我的上下文是:
export const ExpenseContext = createContext();
export const ExpenseProvider = props => {
const [expense, setExpense] = useState(initialExpenses)
const clearItems = () => {
setExpense([])
}
return ( <
ExpenseContext.Provider value = {
[expense, setExpense],
clearItems
} > {
props.children
} <
/ExpenseContext.Provider>
)
}
我想使用这个函数的组件:
const ExpenseList = () => {
const [expense, setExpense] = useContext(ExpenseContext);
const {
clearItem
} = useContext(ExpenseContext);
// const clearItems = () => { normally this works ı know!
// setExpense([])
// }
return ( <
>
<
List > {
expense.map((expense) => {
return <Item key = {
expense.id
}
expense = {
expense
}
/>;
})
} <
/List> <
div className = "text-center" > {
expense.length > 0 && ( <
Button onClick = {
clearItems
}
type = "danger"
shape = "round"
icon = { < DeleteOutlined / >
} >
Clear Expenses <
/Button>
)
} <
/div> < /
>
);
};
在这种情况下,可以直接在组件中使用此函数,而无需尝试传输函数。但我好奇的是我如何设法转移和接收功能。
注意:当我尝试以这种方式使用它时,我收到此错误:TypeError: Object is not a function
React上下文是一种通过 React 节点树传递数据的机制,而无需手动传递 props。使用createContext
为 React 生态系统中的数据结构创建了一个引用,该结构将给定的数据结构公开给子节点。
另一方面,Context.Provider
为使用作为提供程序的子节点的组件提供值。需要记住一些注意事项 - 每当提供程序的值的属性发生变化时,它都会在其所有订阅者(它的后代(中触发重新呈现。提供程序本身不是钩子,因此在使用钩子生成值时,必须使用设置的新值重新呈现提供程序。
代码中有几件事需要解决:
- 在
Context.Provider
中使用useState
, - 返回
useState
的结果作为提供程序值,以及 - 作为提供给提供者的价值的数据结构
在Context.Provider
中使用useState
在反应Context
中消耗useState
的结果时,您必须了解消费对后代的影响,以及它将产生的影响。React 非常擅长确定重新渲染什么以及何时重新渲染,它为您提供了进一步限制该行为的控制。 但是,useState
是一个反应功能组件挂钩,每次更新值时都会触发新的渲染。有关于这一点的规则,优先级和延迟,但可以保证重新渲染任何功能组件消耗useState
钩子。正是出于这个原因,您希望尽可能将提供程序/上下文对象视为纯函数。
返回useState
的结果作为提供程序值
在您的示例中,您将useState
调用的结果按原样返回给上下文提供程序。这给出了一个 React 无法正确订阅和侦听更改的对象结构。
作为提供给提供者的价值的数据结构
对提供程序使用状态时,需要将正确的 JSON 返回给提供程序,以便它可以订阅值更改并通知其后代
用
const providerValue = {
expense,
setExpense,
clearItems
};
<ExpenseContext.Provider value={providerValue}/>
而不是:
<ExpenseContext.Provider value = {
[expense, setExpense],
clearItems
} .../>
您提供给上下文提供程序的对象结构无效。请参阅示例代码笔。
查看这个关于 dev.to 的精彩示例,以便useState
Context
我在评论中怎么说你非常接近,你以同样的方式传递函数、对象和值
const [expenses, setExpenses] = useState([]);
const clearItems = () => {
setExpenses([]);
};
const value = { expenses, setExpenses, clearItems };