首页 > 解决方案 > 为什么子组件没有在反应中呈现

问题描述

我的疑问是为什么不调用子组件 LibrarySubChild,而是进行无限渲染

我的库组件正在从本地 url 获取 JSON,然后设置结果

import React, { Component } from 'react';

     import LibrarySubChild from './Library';

    class Library extends Component {

      state = {
            libraries: []

          };

          componentDidMount() {
            console.log("library componentDidMount method called");
            this.fetchData();
         }

         fetchData = () => {

           fetch('/library/get-all-library',{ mode: 'no-cors'})
           .then(res => res.json())
           .then((data) => {
             this.setState({ libraries: data })
             console.log(this.state.libraries)
           })
           .catch(console.log);

      };

         render() {
           console.log("library render method called");
           const arrLength=this.state.libraries.length;
           return (
             this.state.libraries.length>0 ?
             <LibrarySubChild libraries={this.state.libraries} /> : arrLength
         );
         }

    }

    export default Library;

下面的组件未呈现

 import React, { Component } from 'react';

 const LibrarySubChild = ({ libraries }) => {
   console.log("library sub child render method called");
      return (
        <div>
          <h1>Contact List</h1>
          {libraries.map((library) => (
            <div key={library.libid}>

                <h5>{library.libName}</h5>


            </div>
          ))}
        </div>
      )
    };

    export default LibrarySubChild;

解决此问题的最佳方法是什么

o/p 来自控制台库 componentDidMount 方法称为库 render 方法称为库 componentDidMount 方法称为 (2) [{...}, {...}] 这是控制台输出,它会持续无限时间

标签: reactjs

解决方案


return/render在componentDidMount之前执行。在 Library componentDidMount之后获取状态库值(其长度决定了 LibrarySubChild 是否被渲染)(应该如此)。这会导致子组件在 componentDidMount 之后发生变化,具体来说,创建了一个 LibrarySubChild 的实例,之后,应该使用新的 LibrarySubChild 创建一个新的 Library 实例。

问题是,为什么 LibrarySubChild 没有被渲染——而不是 Library 中的无限 componentDidMount 循环?

答案:如上所示,这是因为(1)创建了一个新的 Library 实例,其库状态值(在构造函数中)重置为 0,而不是简单地运行一次 componentDidMount,因为 React 的 diffing 算法(更多见下文)和(2)状态库值,它决定渲染什么,在组件生命周期的返回/渲染阶段执行,由于(1.),库的状态必然没有任何值 - 重新安装是因为 Library 的根元素以 ap 开头标记并将 LibrarySubChild 更改为根。

在此处输入图像描述

换句话说,请注意在上图中,render 是在 componentDidMount 之前执行的。每当库被实例化(或重新挂载)时,都会执行 fetchData,这会将库状态更改为具有 > 0 个元素,进而导致根元素从 ap 标记更改为 LibrarySubChild,我们知道这会导致重新挂载,然后回到第一方(无限库循环背后的逻辑,从不调用/渲染 LibrarySubChild - 手头的问题)。

现在......您可能在想“componentDidMount 对任何组件只运行一次......总是建议在那里获取数据,对吧......?”

一般来说,当然可以——但重要的是要注意 React 的差异算法(或和解)是是否或任何组件将重新安装的核心。那么,何时必须重新安装组件(从而触发 componentDidMount)?:

每当根元素具有不同的类型时,React 都会拆除旧树并从头开始构建新树。从 to ,或 from to ,或 from to ——其中任何一个都将导致完全重建。

图书馆的根价值在改变吗?事实上,从 ap 标签到超过 p 标签的 LibrarySubChild 组件。

 import React, { Component } from 'react';

 import LibrarySubChild from './Library';

 class Library extends Component {

 state = {
        libraries: []
      };
        //componentDidMount RUNS **AFTER RETURN/RENDER**
            componentDidMount() {

           //Infinitely loops because new instances repeatedly made
           //As React's diffing algorithm notes change in underlying 
           //root element types.

            console.log("library componentDidMount method called");
            this.fetchData();
         } 

        fetchData = () => {
         fetch('/library/get-all-library',{ mode: 'no-cors'})
         .then(res => res.json())
         .then((data) => {

          //Side note: Try not to mutate state directly, like below: 

Suggestion: this.setState({libraries [...this.state.libraries, data]})             

         this.setState({ libraries: data })
         console.log(this.state.libraries)
       })
       .catch(console.log);

   };

     render() {
       console.log("library render method called");
       const arrLength=this.state.libraries.length;
       return (
           this.state.libraries.length>0 ?
         <LibrarySubChild libraries={this.state.libraries} /> : 0
     );
   }
}

export default Library;

祝你好运,莫


推荐阅读