【问题标题】:ReactJS hooks useContext issueReactJS 挂钩 useContext 问题
【发布时间】:2019-09-07 04:52:29
【问题描述】:

我有点喜欢 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={()=&gt;value.fn('ciao')} 有效,但 onClick={()=&gt;value.title = 'new title'} 不会重新渲染组件。

我知道出了点问题,但有人可以帮我说清楚一点吗?

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

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

    【讨论】:

    • 谢谢,现在可以使用了。只有一个问题:useMemo 末尾的 [title, editing] 表示如果更改将触发重新渲染组件的值?
    • 有点,是的。 value 是一个对象,所以如果我不小心,我最终会在每次 LessonManager 渲染时创建一个新对象。这将是一个问题,因为如果我创建一个新对象,这会强制使用 ManagerContext 的所有内容重新渲染,即使对象中的属性没有更改。所以我使用useMemo 只创建一次值对象,然后重用同一个对象。 [title, editing] 数组表示如果 titleediting 发生变化,我希望打破记忆并创建一个新对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多