![](/img/trans.png)
[英]How to test the re-rendering triggered by setState() in componentDidMount() in React 16
[英]React: componentDidMount + setState not re-rendering the component
我对使用componentDidMount
和setState
来做出反应并努力更新自定义组件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.