【问题标题】:Several requests on componentDidMountcomponentDidMount 上的几个请求
【发布时间】:2016-08-10 06:55:13
【问题描述】:

我有一个包含一个父组件和三个子组件的 React 应用程序。在父组件中,我有包含数据的状态并将这些数据在道具中传递给子组件。我也有三个端点,并且必须在父组件的 componentDidMount 函数上发送三个 ajax 请求。如何在 React 中做到这一点?

var Parent = React.createClass({
    getInitialState: function(){
        return ( {
            data1: [],
            data2: [],
            data3: []
        });
    },
    componentDidMount: function() {
        ???
        ???
        ???
    },
    render: function(){
        return (
            <div>
                <Child1 data={this.state.data1} />
                <Child2 data={this.state.data2} />
                <Child3 data={this.state.data3} />
            </div>
        )
    }
})

var Child1 = React.createClass({
    render: function() {
        return (
            <div>
                {this.props.data}   
            </div>
        )
    }
})

var Child2 = React.createClass({
    render: function() {
        return (
            <div>
                {this.props.data}   
            </div>
        )
    }
})

var Child3 = React.createClass({
    render: function() {
        return (
            <div>
                {this.props.data}   
            </div>
        )
    }
})

我想用叠加层“正在加载...”渲染父组件,并在 componentDidMount 上发送 3 个请求,更新状态并将数据作为道具传递给子组件,前提是所有 3 个请求都成功完成,然后渲染/重新渲染这些子组件。如果一个请求有问题,我不想渲染任何子组件(正在加载...一直持续到成功)。异步还是前一个请求成功?

提前致谢。

【问题讨论】:

  • 显示为您的代码..
  • 你可以使用例如这个库:caolan.github.io/async
  • 您可以进行嵌套的 ajax 调用。 call1.success(call2.success(call3.success(setState)))
  • 如果您正在寻找并行性。 successCount = 0; call1.success(successCount++); if (successCount === 3) setState();
  • 我正在寻找并行性,但为了使此功能有效,我想同时处理所有请求。

标签: javascript reactjs


【解决方案1】:

这样的事情可能会奏效。 ajax 调用是伪代码。我假设您正在使用一些 ajax api 库。 - 在这个例子中,我使用了 superagent(没有额外的 promise lib,我只使用了 es6 promise)。 我将 map 与 Promise.all 一起使用 - 基本上,我们等到所有 ajax 请求都返回......在“then”中,我用结果更新状态。一旦 promise.all 被解析,它就会按照你发出请求的顺序传递一个包含每个请求的数组。在“ajaxApi”中——这些是 api 调用。我希望这有帮助。

注意:我在这里假设 es6,因此我使用 promise.all 和一些 es6 简写。如果你没有使用 es6,我很抱歉。告诉我,我可以展示一个非 es6 的解决方案。

var Parent = React.createClass({
    getDefaultProps: function() {
        return {
          ajaxApi: ['foo1','foo2','foo3']
        };
    },
    getInitialState: function(){
        return ( {
            data1: [],
            data2: [],
            data3: []
        });
    },
    componentDidMount: function() {
      Promise.all(this.props.ajaxApi
        .map(a => {
            return new Promise((resolve, reject) => {
                //using superagent here (w/o its promise api), "import request as 'superagent'. You'd import this at the top of your file.
                request.get(a)
                  .end((error, response) => {
                    if (error) {
                      return resolve(response)
                    } else {
                      resolve()
                    }
               })
            })
        )
        .then(v => {
            this.setState({
              data1: v[0],
              data2: v[1],
              data3: v[2]
            })
        })
        .catch(() => {
            console.error("Error in data retrieval")
        })
    },
    render: function(){
        return (
            <div>
                <Child1 data={this.state.data1} />
                <Child2 data={this.state.data2} />
                <Child3 data={this.state.data3} />
            </div>
        )
    }
})

// 这里是一个没有 es6 的 Axios 版本。我在这里做一些假设。我希望你能适应自己的需要。

var Parent = React.createClass({
    // these are your api calls
    getDefaultProps: function() {
        return {
          ajaxApi: ['api/call/1','api/call/2','api/call/3']
        };
    },
    getInitialState: function(){
        return ( {
            data1: [],
            data2: [],
            data3: []
        });
    },

    fetchApiCallData: function(api) {
        return axios.get(api);
    },

    componentDidMount: function() {
       axios.all(this.props.ajaxApi.map(function(api) {
           fetchApiCallData(api)
       })).then(axios.spread(function(req1, req2, req3) {
        // requests complete
           this.setState({
              data1: req1,
              data2: req2,
              data3: req3
            })
       }));
    },
    render: function(){
        return (
            <div>
                <Child1 data={this.state.data1} />
                <Child2 data={this.state.data2} />
                <Child3 data={this.state.data3} />
            </div>
        )
    }
   })

【讨论】:

  • 哇,它让我头脑清醒:) 你能展示一下 es5 解决方案吗? es6 对我来说仍在进行中。非常感谢。我使用 axios 作为 ajax api
  • 好的,我加了一个axios版本。我希望它有所帮助。它没有经过测试,但我认为这应该会让你走上正轨。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多