【问题标题】:How to setState array of objects in component?如何在组件中设置对象数组?
【发布时间】:2018-07-09 07:42:16
【问题描述】:

我从后端获取文件列表并将其推送到处于组件状态的对象数组 (dirloc)。目前控制台日志显示每个文件的多个 dirloc 日志。 一旦所有内容都被推送到dirloc,我想设置状态。怎么做?

    class Load extends Component {
      constructor({ props, token }) {
        super(props, token);
        this.state = {
          nodeRes: [],
          dirloc: []
        };
      }

      componentDidMount() {
        fetch("http://192.168.22.124:3000/loadit/", {
          headers: new Headers({
            authorization: `Bearer ${this.props.token}`,
            "Content-Type": "application/json"
          })
        })
          .then(response => response.json())
          .then(logit => {
            let { dirloc, nodeRes } = this.state;
            logit.map(verifypath => {
              let getpath = verifypath.substring(0, verifypath.lastIndexOf("/"));
              let dirnames = getpath
                .toString()
                .split("/")
                .pop();
              return getpath !== ""
                ? (dirloc.push({
                    getpath: getpath /* for e.g '/folder/of/files/' */,
                    dirnames: dirnames /* array of folder names */,
                    ffiles: verifypath /* full path '/folder/of/files/abc.jpg' */
                  }),
                  this.setState({ dirloc }, () => {
                    console.log(this.state.dirloc);
                  }))
                : (nodeRes.push(verifypath), this.setState({ nodeRes }));
            });
          })
          .then(getdata => this.allFetch(this.state.nodeRes));
      }

    }

    render() {
    const {  dirloc } = this.state;
    let folderView;
    for (var i = 0; i < dirloc.length; i++) {
     if (Object.entries(dirloc).length !== 0 && dirloc.constructor !== Object) {
       folderView = <Filetree fileloc={this.state.dirloc} token={this.props.token} />
    console.log(`dirs: ${dirloc[i].getpath}`)
    } else {
        folderView = null
    }
  }

编辑:问题是当我使用条件语句渲染时,我看到控制台日志多次显示对象,这意味着它多次渲染子组件。我只想用所有必需的对象渲染一次。

【问题讨论】:

    标签: javascript reactjs asynchronous promise es6-promise


    【解决方案1】:

    先生成需要的值,最后再调用一次setState。

    fetch('http://192.168.22.124:3000/loadit/', {
      headers: new Headers({
        authorization: `Bearer ${this.props.token}`,
        'Content-Type': 'application/json',
      }),
    })
      .then((response) => response.json())
      .then((logit) => {
        const { dirloc, nodeRes } = this.state;
        const newDirLoc = [];
        const newNodeRes = [];
        logit.forEach((verifypath) => {
          const getpath = verifypath.substring(0, verifypath.lastIndexOf('/'));
          const dirnames = getpath.toString().split('/').pop();
          getpath !== ''
            ? newDirLoc.push({
              getpath,
              dirnames,
              ffiles: verifypath,
            })
            : newNodeRes.push(verifypath);
        });
        this.setState({
          nodeRes: [...nodeRes, ...newNodeRes],
          dirloc: [...dirloc, ...newDirLoc]
        })
      });
    

    在渲染时,检查循环之前的条件。

    render() {
      const { dirloc } = this.state;
      let folderView;
      if (dirloc.length) {
        for (let i = 0; i < dirloc.length; i++) {
          folderView = <Filetree fileloc={this.state.dirloc} token={this.props.token} />;
          console.log(`dirs: ${dirloc[i].getpath}`);
        }
      } else {
        folderView = null;
      }
    }
    

    已将 Object.entries 替换为简单的长度检查,因为 dirloc 是一个数组。

    【讨论】:

    • 我已经更新了我的问题。问题是当我使用条件语句渲染时,我看到控制台日志多次显示对象,这意味着它多次渲染子组件。我只想用所有必需的对象渲染一次。
    • 使用渲染方法更新了答案,尽管我不确定为什么在这里使用循环,因为除了 console.log 之外,块内没有使用任何循环变量。同样作为一个经验法则,即使 react 的 setState 是异步的并且在执行之前批处理所有语句,最好尽可能少地调用它,因为异步行为无法控制,并且如果您的计算可能会导致多次重新渲染耗时。
    • 我还有一个与此相关的问题,我可以在这里问吗?
    猜你喜欢
    • 2020-11-08
    • 2018-12-10
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 2017-03-24
    相关资源
    最近更新 更多