首页 > 解决方案 > ReactJS 挂钩 useContext 问题

问题描述

我有点喜欢 ReactJS,我正在尝试将 useContext 与钩子一起使用,但我遇到了一些麻烦。我已经阅读了几篇文章,但我无法理解。

我理解它的目的,但我不知道如何使它正常工作。如果我是正确的,那么目的是能够避免将道具传递给每个孩子,并能够在组件树的任何深度访问来自公共提供者的值。这包括函数和状态值。如果我错了,请纠正我。

我一直在使用以下文件进行测试。这是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'}不会重新渲染组件。

我知道出了点问题,但是有人可以让我更清楚吗?

标签: reactjsreact-hooks

解决方案


为了进行重新渲染,某处的某些组件必须调用 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>
  )
}

推荐阅读