React JS:this.setState和JSON.parse

时间:2018-02-11 16:28:19

标签: javascript json reactjs react-native react-router

我有问题,我不知道如何解决它。我向我的api提出了一个请求,它回复了这样一个对象:

{"_id":"5a806648300caf0072c7254a","mail":"email@email.com"}

我想将反应组件打印到邮件中。在我的" componentDidMount()"功能我收到邮件,所以我的api没问题。但是,当我想设置我的"用户"变量,我不能在我的组件中打印变量......它说它未定义。

这是我的代码:

class UserList extends Component {
    constructor(props){
        super(props);
        this.state = {users:[]}
    }
    componentDidMount() {
        //here my function that store the response from my api
        GetData('http://localhost:3333/users', 'username=admin', 
        (res) => 
        {
            this.setState({users: JSON.parse(res)});
            //Here I can log the mail
            console.log(this.state.users[0].mail);
        })
    }
    render() {
        return (
            <table>
                <thead>
                <tr>
                    <th>EMAIL</th>
                </tr>
                </thead>
                <tbody>
                    <tr>
                        //Here it is 'undefined'
                        <td>{this.state.users[0].mail}</td>
                    </tr>
                </tbody>
            </table>
        );
    }
}

感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

您不应直接使用异步操作中的值。

由于componentDidMount()中的GetData是异步函数,因此获取数据需要一些时间。因此,在初始渲染中,user处于状态为空。

最好使用加载指示器,直到获取数据,并仅在收到数据时显示数据。

您可以使用如下。

class UserList extends Component {
    constructor(props){
        super(props);
        this.state = {users:[]},
        loading: false
    }
    componentDidMount() {
        //here my function that store the response from my api
        this.setState({loading: true});
        GetData('http://localhost:3333/users', 'username=admin', 
        (res) => 
        {
            this.setState({users: JSON.parse(res), loading: false});
            //Here I can log the mail
            console.log(this.state.users[0].mail);
        })
    }
    render() {
        if(this.state.loading){
            return (<div> Loading... </div>)
        }
        return (
           <div>
            <table>
                <thead>
                <tr>
                    <th>EMAIL</th>
                </tr>
                </thead>
                <tbody>
                   {this.state.users.length > 0 &&
                    <tr>

                      <td>{this.state.users[0].mail || ''}</td>

                    </tr>
                   }
                </tbody>
            </table>
        </div>
        );
    }
}

使用可以使用map循环如下

               {this.state.users.length > 0 && this.state.users.map(user => 
               return(
                    <tr>

                      <td>{user.mail || ''}</td>

                    </tr>)
                   }

答案 1 :(得分:0)

在上述情况下,问题在于理解React的组件生命周期。

请查看reference

在渲染发生后发生ComponentDidMount。

层次结构将是1.构造函数2. componentWillMount 3. render 4. componentDidMount

如果通过将ComponentDidMount替换为ComponentWillMount

来修改代码
componentWillMount() {
     //here my function that store the response from my api
        GetData('http://localhost:3333/users', 'username=admin', 
        (res) => 
        {
            this.setState({users: JSON.parse(res)});
            //Here I can log the mail
            console.log(this.state.users.mail);
        })
  }

如果api正常工作,它将提供数据。

但等待api的响应是一个对象,用数组初始化状态在概念上也不正确我想是的。

当我在Typescript中处理大部分项目时,状态初始化对我来说很重要。

constructor(props){
        super(props);
        this.state = {users:{
                         mail: ''
                      }}
}

个人偏好是检查用户状态是否未定义,否则肯定不会导致任何未定义或错误。

答案 2 :(得分:-1)

React安装组件生命周期是:

  • 构造
  • componentWillMount
  • 呈现
  • componentDidMount

在此处查看更多内容:https://reactjs.org/docs/react-component.html#mounting

当你的组件挂载时,this.state.users是一个空数组。

您可以更改渲染方法:

class UserList extends Component {
    constructor(props){
        super(props);
        this.state = {users:[]}
    }
    componentDidMount() {
        //here my function that store the response from my api
        GetData('http://localhost:3333/users', 'username=admin', 
        (res) => 
        {
            // After setState react runs updating lifecycle methods (https://reactjs.org/docs/react-component.html#updating)
            this.setState({users: JSON.parse(res)});
            //Here I can log the mail
            console.log(this.state.users[0].mail);
        })
    }
    render() {
        // if users are not loaded, we return null from render function
        if (this.state.users.length === 0) {
            return null;
        }
        
        return (
            <table>
                <thead>
                <tr>
                    <th>EMAIL</th>
                </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>{this.state.users[0].mail}</td>
                    </tr>
                </tbody>
            </table>
        );
    }
}