2017-10-16 16 views
0

我遇到了具有某些必需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的。

+0

可能是你想结帐这个https://stackoverflow.com/questions/43312223/asynchronous-call-in-componentwillmount-finishes-after-render-method – praveenweb

回答

3

因为您正在使用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 
    } 
}; 

还有其他方法可以做到这一点。您可以按照您的建议在缩减器中设置firstNamelevel的默认值,或者您始终可以使用user prop对UserHeader进行渲染,并决定在未设置值subValues时显示的内容。

0

添加一个加载程序组件或如下所示的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> 
    ); 
} 
相关问题