React JS:this.setState 和 JSON.parse

Posted

技术标签:

【中文标题】React JS:this.setState 和 JSON.parse【英文标题】:React JS : this.setState and JSON.parse 【发布时间】:2018-07-21 20:50:57 【问题描述】:

我有一个问题,我不知道如何解决它。我正在向我的 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>
        );
    

感谢您的帮助!

【问题讨论】:

【参考方案1】:

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

请查看reference。

ComponentDidMount 在渲染发生后发生。

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

如果代码被修改为用 ComponentWillMount 替换 ComponentDidMount

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】:

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

由于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>)
                   

【讨论】:

【参考方案3】:

React 安装组件生命周期是:

构造函数 组件WillMount 渲染 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>
        );
    

【讨论】:

我是如何使用 fetch 的? @SupunAbesekara 您可以将 GetData 替换为 window.fetch 并使用承诺链,例如:window.fetch(url, data).then(result =&gt; result.json()).then(json =&gt; this.setState(users: json.users);

以上是关于React JS:this.setState 和 JSON.parse的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React JS 中的 css 转换结束后使用 setState?

如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?

整理下react中常见的坑

react中this.setState的理解

react setState

react的this.setState中的坑