简体   繁体   English

React组件未在setState({})上重新呈现

[英]React component not re-rendering on setState({})

I've read through a bunch of other posts, and I can't figure out why my files don't load. 我已经阅读了许多其他文章,但无法弄清楚为什么我的文件无法加载。

I'm using setState not state = and so on. 我正在使用setState而不是state =等等。 But anyway, here's the code, if anybody has any ideas, I'd be very happy! 但是无论如何,这是代码,如果有人有任何想法,我会很高兴的!

Essentially, the component mounts, then runs getClientFiles() , which pulls an array of references. 本质上,该组件将挂载,然后运行getClientFiles() ,该操作将提取引用数组。 Then this function executes getFileData() which takes each of those reference IDs, and pulls back the file information, which gets stored in this.state.client_files , and then mapped over in the JSX. 然后,此函数执行getFileData()并获取每个引用ID,然后拉回文件信息,该信息将存储在this.state.client_files ,然后映射到JSX中。

The currentUser.first_name populates just fine. currentUser.first_name可以很好地填充。 But my understanding is that it's running the getClientFiles() asynchronously, and therefore doesn't have the file_refs on first run. 但是我的理解是,它异步运行getClientFiles() ,因此第一次运行时没有file_refs My assumption was, though, by using setState({ file_refs: file_refs}) is that the component should re-render... but it doesn't. 不过,我的假设是,通过使用setState({ file_refs: file_refs})可以重新渲染组件……但事实并非如此。

Note: If I refresh the page, the files load. 注意:如果刷新页面,则会加载文件。 So it is only on initial login that they don't populate. 因此,只有在初始登录时,它们才会填充。

I'm fairly new to React... so please be kind! 我是React的新手,所以请客气! If you notice other issues in the code here, it'd be great if you pointed them out. 如果您在此处的代码中发现其他问题,请指出来解决。

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>
    );
  }
}

Update: I have updated the code to the follow based on suggestions in the answers. 更新:我已经根据答案中的建议将代码更新为以下内容。

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();
          })
        }
      });
    }

Unfortunately, still not getting the files until after a page refresh :( 不幸的是,直到页面刷新后仍无法获取文件:(

Your problem is likely on these lines: 您的问题可能在以下几行:

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

setState is asynchronous, so you will not have guaranteed access to this.state immediately after invoking that method. setState是异步的,因此调用该方法后,不能保证立即访问this.state You need to move the call to getFileData into the second parameter of setState , that will ensure that it will be invoked after state is actually set (ie you can use this.state ): 您需要getFileData的调用移到setState的第二个参数中,以确保在实际设置state之后可以调用它(即,可以使用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();
            });
        });
}

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

I managed to solve this by doing the following: 通过执行以下操作,我设法解决了这一问题:

Setting state with returned_data: false , and then triggering the getClientFiles() function prior to returning the app. 使用return_data设置状态returned_data: false ,然后在返回应用程序之前触发getClientFiles()函数。 The function then sets state returned_data: true . 然后该函数设置状态returned_data: true

render() {

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

      return( <App /> );
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM