ReactJS钩住useContext问题

时间:2019-09-07 04:52:29

标签: reactjs react-hooks

我有点喜欢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'}不会重新呈现组件。

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

1 个答案:

答案 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>
  )
}