web-dev-qa-db-ja.com

componentWillMountに状態を設定できません

メッセージオブジェクトの配列を返すaxiosを介してデータベースにAPI呼び出しを行う簡単なチャットアプリを作成しています。 componentWillMountでaxios呼び出しを行うと、データを取得できます。次に、会話を表示するようにsetStateを試みています。コードは次のとおりです。

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プロパティを解析します。助けてくれてありがとう!」

10
Phil

あなたの場合、非同期コールバック内で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.
  }
}; 
11
Pranesh Ravi

componentWillMount()は、マウントが発生する直前に呼び出されます。 render()の前に呼び出されるため、このメソッドで状態を設定しても再レンダリングはトリガーされません。このメソッドに副作用やサブスクリプションを導入しないでください。 ドキュメント

したがって、componentDidMount as-を呼び出す必要があります

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