繁体   English   中英

反应:componentDidMount + setState 不重新渲染组件

[英]React: componentDidMount + setState not re-rendering the component

我对使用componentDidMountsetState来做出反应并努力更新自定义组件setState ,这似乎是推荐的做法。 下面是一个示例(包括一个用于获取数据的axios API 调用):

import React from 'react';
import {MyComponent} from 'my_component';
import axios from 'axios';


export default class Example extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            data: []
        };
    }

    GetData() {
        return axios.get('http://localhost:5000/<route>');
    }

    componentDidMount() {
        this.GetData().then(
                (resp) => {
                    this.setState(
                        {data: resp.data}
                    )
                }
            )
    }

    render() {
        return (
            <MyComponent data={this.state.data} />
        );
  } 
}

render()下方执行console.log(this.state.data)表明this.state.data确实得到了更新(从[]到 API 返回的任何内容)。 但是,问题似乎是MyComponent没有被componentDidMount重新呈现。 来自 Facebook 的反应文档:

在此方法中设置状态将触发重新渲染。

这似乎不是这里的情况: MyComponent的构造函数只被调用一次(其中this.props.data = [] )并且组件不会再次被渲染。 如果有人能解释为什么会这样,以及是否有解决方案或完全不同的方式来完成更新,我会很棒。

更新

我已经添加了MyComponent的代码(减去一些不相关的功能,如... )。 console.log(data_array)打印一个空数组。

import React from 'react';

class DataWrapper {
  constructor(data) {
    this._data = data;
  }

  getSize() {
    return this._data.length;
  }

     ...
}


export class MyComponent extends React.Component {
      constructor(props) {
        super(props);

        this._dataWrapper = new DataWrapper(this.props.data);

        this.state = {
          data_array: this._dataWrapper,
        };

      }

    render() {
        var {data_array} = this.state;
        console.log(data_array);
        return (
                ...
        );
    }
 }

您正在成为这种反模式的受害者

MyComponent构造函数中,它只在第一次挂载时被调用,通过new DataWrapper传递你的空数组,现在你有一些本地状态,无论你的父级做什么都不会更新。

最好有一个事实来源,任何地方都只有一个状态对象(特别是对于 ajax 响应之类的东西),并通过 props 传递它们。 事实上,通过这种方式,您甚至可以将MyComponent编写为一个简单的函数,而不是一个类。

class Example extends Component {
  state = { data: [] }

  GetData() { .. }

  componentDidMount() {
    this.GetData().then(res =>
      this.setState({data: new DataWrapper(res.data)})
    )
  }

  render() { return <MyComponent data={this.state.data} /> }
}

...

function MyComponent (props) {
  // props.data will update when your parent calls setState
  // you can also call DataWrapper here if you need MyComponent specific wrapper
  return (
    <div>..</div>
  )
}

换句话说,azium 所说的是您需要将接收组件变成受控组件。 意思是,它根本不应该有 state 直接使用道具。

是的,甚至把它变成一个功能组件。 这有助于您牢记功能组件通常没有状态(可以将状态放入其中,但...分离关注点)。

如果您需要从该受控组件编辑状态,请通过 props 提供功能并在“主”组件中定义功能。 因此,主组件只是将控制权交给子组件。 他们想要与父母交谈的任何事情。

我不会在这里发布代码,因为您需要进行的修改可以忽略不计。 在受控组件中有 this.state 的地方,更改为 this.props。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM