我有点喜欢ReactJS,并且试图将useContext与钩子一起使用,但是遇到了一些麻烦。我已经阅读了几篇文章,但我听不懂。
我了解它的目的,但是我不知道如何使其正常工作。如果我是正确的,其目的是能够避免将prop传递给每个孩子,并能够在组件树的任何深度访问来自公共提供程序的值。这包括功能和状态值。如果我错了,请纠正我。
我一直在测试以下文件。这是ManagerContext.js
文件:
import { createContext } from 'react';
const fn = (t) => {
console.log(t);
}
const ctx = createContext({
title: 'This is a title',
editing: false,
fn: fn,
})
let ManagerContext = ctx;
export default ManagerContext;
然后我有一个LessonManager.js
文件,该文件在我的主应用程序中使用:
import React from 'react';
import LessonMenu from './LessonMenu.js';
export default function LessonManager() {
return (
<LessonMenu />
)
}
最后是LessonMenu.js
:
import React from 'react';
import 'rsuite/dist/styles/rsuite.min.css';
import ManagerContext from './ManagerContext.js';
export default function LessonMenu() {
const value = React.useContext(ManagerContext);
return (
<div>
<span>{value.title}</span>
<button
onClick={()=>value.fn('ciao')}
>click</button>
<button
onClick={()=>value.title = 'new title'}
>click</button>
</div>
)
}
在LessonMenu.js文件中,onClick={()=>value.fn('ciao')}
有效,但是onClick={()=>value.title = 'new title'}
不会重新呈现组件。
我知道出了点问题,但是有人可以让我更清楚吗?
答案 0 :(得分:2)
为了进行重新渲染,某处的某些组件必须调用setState。您的代码不会执行此操作,因此不会进行渲染。
您为ManagerContext完成的设置将创建一个默认值,但这仅在您未在组件树中呈现任何ManagerContext.Provider的情况下才会使用。那就是您现在正在做的,但是几乎可以肯定不是您想要的。您将希望在树的顶部附近具有一些组件来呈现ManagerContext.Provider。该组件可以是状态所在的位置,并且它向下发送的数据中将包含一个或多个设置状态的函数,从而触发重新呈现:
export default function LessonManager() {
const [title, setTitle] = useState('SomeOtherTitle');
const [editing, setEditing] = useState(false);
const value = useMemo(() => {
return {
title,
setTitle,
editing,
setEditing,
log: (t) => console.log(t)
}
}, [title, editing]);
return (
<ManagerContext.Provider value={value} >
<LessonMenu />
</ManagerContext.Provider/>
)
}
// used like:
export default function LessonMenu() {
const value = React.useContext(ManagerContext);
return (
<div>
<span>{value.title}</span>
<button onClick={() => value.log('ciao')}>
click
</button>
<button onClick={() => value.setTitle('new title')}>
click
</button>
</div>
)
}