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

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

问题描述:

我是相当新的反应和努力更新自定义组件使用componentDidMountsetState,这似乎是推荐的方式。下面的例子(包括axios API调用来获取数据):反应:componentDidMount + setState不重新渲染组件

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 = [])和成分不会再次呈现。如果有人能够解释这是为什么,以及是否有解决方案或完全不同的方式来完成更新,我会很棒。

UPDATE

我已经添加了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 (
       ... 
     ); 
    } 
} 
+0

你可以显示'MyComponent'的代码吗?你在容器组件中做的看起来是正确的,但是在子组件内可能会发生一些奇怪的事情。 –

+3

构造函数不必多次调用。 React已经创建了这个对象,它不需要再次这样做。如果你在'componentWillReceiveProps'中记录一些东西,你会看到工作正常。如果MyComponent在'this.props.data'中呈现出某些内容,那么它将被更新。 –

+0

是的,为什么需要再次调用构造函数?尝试在渲染中放置一个console.log以确认它渲染两次。 – Conan

你是this antipattern.

的牺牲品在MyComponent构造函数,它只有被称为第一次安装,通过你的空数组通过new DataWrapper现在你将永远不会更新一些地方的国家没有重要的是你的父母做什么。

拥有一个真相源,任何地方只有一个状态对象(特别是对于像Ajax响应),并通过道具传递这些对象总是更好。事实上,你甚至可以把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> 
) 
}