Reactjs 为什么在通过上下文更新单个状态时组件会完全重新呈现?

Reactjs 为什么在通过上下文更新单个状态时组件会完全重新呈现?,reactjs,typescript,react-typescript,fluent-ui,fluentui-react,Reactjs,Typescript,React Typescript,Fluent Ui,Fluentui React,我创建了一个包含两列的页面: 在一列中,显示项目列表 在另一列中,我应该显示一些与所选项目相关的信息 到目前为止,我掌握的代码是: import { INavLink, INavLinkGroup, INavStyles, Nav } from "@fluentui/react"; import React, { createContext, useContext, useState } from "react"; interface HistoryTt

我创建了一个包含两列的页面:

  • 在一列中,显示项目列表
  • 在另一列中,我应该显示一些与所选项目相关的信息
  • 到目前为止,我掌握的代码是:

    import { INavLink, INavLinkGroup, INavStyles, Nav } from "@fluentui/react";
    import React, { createContext, useContext, useState } from "react";
    
    interface HistoryTtem {
      id: string;
    }
    
    interface AppState {
      selectedItem: string | undefined;
      updateSelectedItem: (value: string | undefined) => void;
      items: Array<HistoryTtem>;
    }
    
    const AppContext = createContext<AppState>({
      selectedItem: undefined,
      updateSelectedItem: (value: string | undefined) => {},
      items: []
    });
    
    const App = () => {
      const Column1 = () => {
        const rootState: AppState = useContext(AppContext);
    
        const getNavLinks: Array<INavLink> = rootState.items.map((item) => ({
          name: item.id,
          key: item.id,
          url: ""
        }));
    
        const groups: Array<INavLinkGroup> = [
          {
            links: getNavLinks
          }
        ];
    
        const navStyles: Partial<INavStyles> = {
          root: {
            boxSizing: "border-box",
            border: `1px solid #eee`,
            overflowY: "auto"
          }
        };
    
        const onItemClick = (
          e?: React.MouseEvent<HTMLElement>,
          item?: INavLink
        ) => {
          if (item && item.key) {
            rootState.updateSelectedItem(item.key);
          }
        };
    
        return (
          <Nav
            onLinkClick={onItemClick}
            selectedKey={rootState.selectedItem}
            ariaLabel="List of previously searched transactions"
            styles={navStyles}
            groups={groups}
          />
        );
      };
    
      const Column2 = () => {
        return <div>aaa</div>;
      };
    
      const [historyItems, setHistoryItems] = useState<Array<HistoryTtem>>([
        {
          id: "349458457"
        },
        {
          id: "438487484"
        },
        {
          id: "348348845"
        },
        {
          id: "093834845"
        }
      ]);
      const [selectedItem, setSelectedItem] = useState<string>();
    
      const updateSelectedItem = (value: string | undefined) => {
        setSelectedItem(value);
      };
    
      const state: AppState = {
        selectedItem: selectedItem,
        updateSelectedItem: updateSelectedItem,
        items: historyItems
      };
    
      return (
        <AppContext.Provider value={state}>
          <div>
            <Column1 />
            <Column2 />
          </div>
        </AppContext.Provider>
      );
    };
    
    export default App;
    
    import{INavLink,INavLinkGroup,INavStyles,Nav}来自“@fluentui/react”;
    从“React”导入React,{createContext,useContext,useState};
    界面历史记录{
    id:字符串;
    }
    接口应用状态{
    selectedItem:string |未定义;
    updateSelectedItem:(值:字符串|未定义)=>void;
    项目:阵列;
    }
    
    const AppContext=createContext。

    不应该嵌套组件函数

    Column1
    的标识会随着
    App
    的每次渲染而改变,因为它是一个内部函数,这使React认为它需要协调所有内容


    Column1
    Column2
    移动到模块级。

    使
    反应重新渲染器
    的原因有两个:

  • 状态变化

  • 更换道具


  • 你有一个
    应用程序组件
    ,它是你的
    组件的根
    ,它有一个
    selectedItem
    状态,当点击
    项目时,该状态会发生变化,因此你有了一个新状态,新状态会导致重新加载。事实上,我每次都犯了一个严重的错误,因为到目前为止,我认为只有一个组件在其中定义使用组件是一种好的做法,但这实际上是在做坏事。。。该模式可能仅在HOC中使用。从技术上讲,您可以使用
    React.useCallback()
    来提示React内部组件不会更改,但这更令人困惑。:)或者,正如我在回答中所解释的,组件中的一个变化:)@AKX Sure:),这将是第3个