在渲染前更新状态:propType标记为必需但未定义
问题描述:
我遇到了具有某些必需propTypes的组件的问题。在渲染前更新状态:propType标记为必需但未定义
我得到的错误是:
Warning: Failed prop type: The prop `firstname` is marked as required in `UserHeader`, but its value is `undefined`.
in UserHeader (at App.js:32)
in App (created by Connect(App))
in Connect(App) (at index.js:17)
in Provider (at index.js:16)
而且我的代码...
import React, { Component } from 'react';
import { connect } from 'react-redux';
import ErrorBoundary from './containers/ErrorBoundary'
import UserHeader from './components/UserHeader';
import Header from './components/Header';
class App extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
// Pretend this is an API call that takes a second
setTimeout(() => {
const data = {
user: {
firstname: 'bughunter',
level: 55
}
};
this.props.didMountHandler(data)
}, 1000);
}
render() {
return (
<ErrorBoundary>
<Header />
<UserHeader
firstname={this.props.firstname}
level={this.props.level}
/>
</ErrorBoundary>
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
firstname: state.user.firstname,
level: state.user.level
}
};
const mapDispatchToProps = dispatch => ({
didMountHandler: data => {
dispatch({
type: 'USER_DATA_RECEIVED',
data
});
}
})
const AppContainer = connect(
mapStateToProps,
mapDispatchToProps
)(App);
export default AppContainer;
我修改render
方法之前的状态已经调用,所以我很困惑如何在setTimeout
完成之前正在检查UserHeader
道具吗?
我怎么能延迟渲染/ propChecking直到setTimeout
已经完成?
我想到了创建存储时设置一些初始默认状态,就像这样:
{
user: {
firstname: '',
level: 0
}
}
......但似乎有点hackish的。
答
因为您正在使用setTimeout,所以您不会修改render
之前的状态。渲染不会等待您的setTimeout
,并在调用componentWillMount
后直接调用。
你必须在redux reducer中设置一些默认值。你可以只设置在减速
user: null,
....
和渲染检查时,如果有用户或不
render() {
const { user } = this.props;
{ user && <UserHeader firstname={user.firstname} level={user.level} /> }
在
mapStateToProps
而只是复制整个user
OBJ:
const mapStateToProps = (state, ownProps) => {
return {
user: state.user
}
};
还有其他方法可以做到这一点。您可以按照您的建议在缩减器中设置firstName
和level
的默认值,或者您始终可以使用user
prop对UserHeader
进行渲染,并决定在未设置值subValues时显示的内容。
答
添加一个加载程序组件或如下所示的null。并使用本地状态。
state = { initialized: false }
componentWillMount() {
// Pretend this is an API call that takes a second
setTimeout(() => {
const data = {
user: {
firstname: 'bughunter',
level: 55
}
};
this.props.didMountHandler(data)
this.setState({ initialized: true });
}, 1000);
}
render(){
if(!this.state.initialized){
return null;
}
return (
<ErrorBoundary>
<Header />
<UserHeader
firstname={this.props.firstname}
level={this.props.level}
/>
</ErrorBoundary>
);
}
可能是你想结帐这个https://stackoverflow.com/questions/43312223/asynchronous-call-in-componentwillmount-finishes-after-render-method – praveenweb