无法在componentWillMount中设置状态 [英] Can't set state in componentWillMount

查看:111
本文介绍了无法在componentWillMount中设置状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个简单的聊天应用程序,在该应用程序中,我通过axios对数据库进行api调用,该API返回了一组消息对象.我可以在componentWillMount中进行axios调用时获取数据.然后我试图设置状态以显示对话.这是代码:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })
};

我看过一些有关生命周期功能和设置状态的帖子,看来我在做正确的事情.

再次突出显示,axios调用工作正常,设置状态不工作.我仍然看到一个空数组.预先感谢!

这是专门针对我的问题的解决方案.它埋在评论中,所以我想把它留在这里.

我发现了问题.实际上是我解析数据的方式....messages.content上的散布运算符不起作用,因为messages.content不存在.messages[i] .content存在因此,我的解决方法是只传播...消息,然后在子组件中映射对象并解析.content属性.感谢帮助人员!"

解决方案

在您的情况下,您的setState()将不起作用,因为您在异步回调中使用了setState()

工作小提琴: https://jsfiddle.net/xytma20g/3/

您正在进行异步API调用.因此,仅在接收到数据后才调用setState.对于componentWillMountcomponentDidMount,它不执行任何操作.您需要处理渲染中的空白message.当您从API接收数据时,请将数据设置为状态,然后组件将使用新状态重新渲染,该状态将反映在渲染中.

伪代码:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })

  render(){
    if(this.state.messages.length === 0){
     return false //return false or a <Loader/> when you don't have anything in your message[]
    }

   //rest of your render.
  }
}; 

I am creating a simple chat app where I make an api call to my database via axios which returns an array of message objects. I am able to get the data when I make an axios call in componentWillMount. Then I am trying to setState to display the conversation. Here's the code:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })
};

I have seen some posts concerning lifecycle functions and setting state, and it seems like I'm doing the right thing.

Again to highlight, axios call working fine, setting the state is not working. I am still seeing an empty array. Thanks in advance!

EDIT: Here is the solution to my issue specifically. It was buried in a comment, so I thought I'd leave it here..

"I discovered the issue. It was actually in how I was parsing my data. The spread operator on ...messages.content didn't work because messages.content doesn't exist. messages[i].content exists. So my fix was to spread just ...messages Then in a child component I map over the objects and parse the .content property. Thanks for the help guys!"

解决方案

In your case, your setState() won't work because you're using setState() inside an async callback

Working Fiddle: https://jsfiddle.net/xytma20g/3/

You're making an API call which is async. So, the setState will be invoke only after receiving the data. It does not do anything with componentWillMount or componentDidMount. You need to handle the empty message in your render. When you receive your data from the API, set that data to the state and component will re-render with the new state which will be reflected in your render.

Pseudo code:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })

  render(){
    if(this.state.messages.length === 0){
     return false //return false or a <Loader/> when you don't have anything in your message[]
    }

   //rest of your render.
  }
}; 

这篇关于无法在componentWillMount中设置状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆