React组件未在setState({})

时间:2018-08-15 22:46:52

标签: javascript reactjs state

我已经阅读了许多其他文章,但无法弄清楚为什么我的文件无法加载。

我使用的是setState,而不是state =,依此类推。但是无论如何,这是代码,如果有人有什么想法,我会很高兴的!

从本质上讲,该组件将挂载,然后运行getClientFiles(),这将提取引用数组。然后,此函数执行getFileData(),它获取这些引用ID中的每个引用ID,并拉回文件信息,该信息存储在this.state.client_files中,然后映射到JSX中。

currentUser.first_name可以很好地填充。但是我的理解是它正在异步运行getClientFiles(),因此在第一次运行时没有file_refs。我的假设是,尽管使用setState({ file_refs: file_refs})是组件应该重新呈现...但事实并非如此。

注意:如果刷新页面,则会加载文件。因此,只有在初次登录时,他们才会填充。

我对React还是很陌生...所以请客气!如果您在此处的代码中发现其他问题,请指出来解决。

class Client extends Component {

  constructor(props) {
    super(props)

    this.state = {
      header: "PartnerPortal",
      client_files: [],
      file_refs: [],
      user_id: ""
    };

  }

    componentDidMount() {
        this.getClientFiles();
    };

    getClientFiles() {
      let id = this.props.currentUser.user_id;
      let file_refs = [];

      axios.get(`/users/get-client-files/${id}`)
        .then ( res => {
          console.log(res.data.response);
          let response = res.data.response;

          for (let i = 0; i < response.length; i++) {
            file_refs.push(response[i].file_id);
          };
          this.setState({
            file_refs: file_refs
          })
          this.getFileData();
        })
    }


    getFileData() {

      let fileRefs = this.state.file_refs;
      let fileData = [];

      for (let i = 0; i < fileRefs.length; i++) {
        axios.get("/files/get-file/" + fileRefs[i])
          .then( res => {
            fileData.push(res.data.response);
            this.setState({
              client_files: fileData,
              data_returned: true
            })
          })
          .catch( err => console.log(err.response.data))
      }
    }

  render() {

      return(
      <Fragment>
         <div className="container">
          <div className="row">
            <div className="col-lg-12">
                <h4>
                  <em>Welcome, {this.props.currentUser.first_name} {this.props.currentUser.last_name}</em>
                </h4>
                <h5>
                  <em>{ this.props.currentUser.client_name}</em>
                </h5>

                <div className="fileBox">

                  {this.state.client_files.map(( file, i ) => (
                    <a key={i} style={styles.linkCard} href={file.file_url} target="_blank">
                    <div key={i} className="clientCard">

                      { file.file_type === "PDF" &&
                        <span><i className="fas fa-file-pdf pdf"></i></span>
                      }
                      { file.file_type === "DOC" &&
                        <span><i className="fas fa-file-alt doc"></i></span>
                      }
                      { file.file_type === "Directory" &&
                        <span><i className="fas fa-folder-open dir"></i></span>
                      }
                      { file.file_type === "Presentation" &&
                        <span><i className="fas fa-file-powerpoint ppt"></i></span>
                      }
                      <p>{file.file_name}</p>

                    </div>
                    </a>
                    ))}
                </div>
              </div>
            </div>
          </div>
      </Fragment>
    );
  }
}

更新: 我已根据答案中的建议将代码更新为以下代码。

componentDidMount() {
        this.getClientFiles();
    };

    getClientFiles() {
      let id = this.props.currentUser.user_id;
      let file_refs = [];

      axios.get(`/users/get-client-files/${id}`)
        .then ( res => {
          console.log(res.data.response);
          let response = res.data.response;

          for (let i = 0; i < response.length; i++) {
            file_refs.push(response[i].file_id);
            this.setState({
              file_refs
            }, () => {
            this.getFileData();
          })
        }
      });
    }

不幸的是,直到页面刷新后仍无法获取文件:(

2 个答案:

答案 0 :(得分:3)

您的问题可能在以下几行:

this.setState({
    file_refs: file_refs
})
this.getFileData();

setState是异步的,因此调用该方法后,不能保证立即访问this.state。您需要将对getFileData的调用移到setState的第二个参数中,以确保在实际设置状态后调用它(即,您可以使用this.state):

getClientFiles() {
    let id = this.props.currentUser.user_id;
    let file_refs = [];

    axios.get(`/users/get-client-files/${id}`)
        .then(res => {
            console.log(res.data.response);
            let response = res.data.response;

            for (let i = 0; i < response.length; i++) {
                file_refs.push(response[i].file_id);
            }
            this.setState({
                file_refs
            }, () => {
                this.getFileData();
            });
        });
}

在此处查看更多信息:https://reactjs.org/docs/react-component.html#setstate

答案 1 :(得分:0)

我设法通过以下方法解决了这个问题:

使用returned_data: false设置状态,然后在返回应用程序之前触发getClientFiles()函数。然后,该函数设置状态returned_data: true

render() {

      if (this.state.returned_data === false) {
        this.getClientFiles();
      }

      return( <App /> );
    }