【问题标题】:In React.js should I make my initial network request in componentWillMount or componentDidMount?在 React.js 中,我应该在 componentWillMount 还是 componentDidMount 中发出我的初始网络请求?
【发布时间】:2017-05-27 12:03:48
【问题描述】:

在反应文档中,它建议在 componentDidMount 方法中发出初始网络请求:

componentDidMount() 在组件安装后立即调用。需要 DOM 节点的初始化应该放在这里。如果您需要从远程端点加载数据,这是一个实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。

如果在渲染组件之前调用componentWillMount,在这里发出请求并设置状态不是更好吗?如果我在componentDidMount 中这样做,则渲染组件,发出请求,更改状态,然后重新渲染组件。为什么在呈现任何内容之前发出请求不是更好?

【问题讨论】:

  • 即使您从componentWillMount 方法调用组件,请求也可能在渲染组件时尚未完成。

标签: javascript reactjs


【解决方案1】:

您应该在componentDidMount 中提出请求。

如果在渲染组件之前调用了componentWillMount,那么在这里发出请求并设置状态不是更好吗?

否,因为在组件渲染时请求不会完成。

如果我在 componentDidMount 中这样做,则渲染组件,发出请求,更改状态,然后重新渲染组件。为什么在呈现任何内容之前发出请求不是更好?

因为任何网络请求都是异步。除非您缓存了数据,否则无论如何您都无法避免第二次渲染(在这种情况下,您根本不需要触发请求)。 您无法通过提前触发来避免第二次渲染。这无济于事。

在未来的 React 版本中,我们预计 componentWillMount 在某些情况下会触发不止一次,因此您应该使用 componentDidMount 进行网络请求

【讨论】:

  • 通常我会使用isFetching 状态进行网络请求。 1.初始isFetching = false,用空数据渲染。 2.componentDidMount,调度获取请求,将isFetching设置为true,使用<Loading >组件进行渲染。 3. 获取成功,将isFetching设置为false,用获取到的数据进行渲染。是否有一种好的(安全)方法可以使用 <Loading> 组件进行初始渲染,而不是使用空数据进行渲染。谢谢?。
  • 另一种选择可能是从父组件获取网络数据,然后通过道具将其传递给子组件,从而避免第二次渲染。
  • 我知道这现在超出了范围,因为 componentWillMount 已被弃用,但如果网络调用是同步的呢?
  • 对不起,如果我的问题很愚蠢。如果我在componentWillMount中取数据,即使没有破坏第一次渲染的组件,`componentWillMount`中的取数据函数是否会比取数据componentDidMount函数调用早一点,导致在我们获取数据的速度会快一点吗?
【解决方案2】:

你应该使用componentDidMount

为什么在渲染之前提出请求不是更好?

因为:

  • 您的请求几乎肯定不会在组件被渲染之前完成(除非渲染大量标记,或者您处于零延迟量子纠缠连接上),并且组件最终需要重新- 再次渲染,大部分时间
  • 在服务器端渲染期间也会调用componentWillMount(如果适用)

但是,如果您要问,在componentWillMount发起一个请求不是更好吗(没有实际处理它),我肯定会说是(ES6),并且我自己这样做是为了偶尔减少几毫秒的加载时间:

componentWillMount() {
    // if window && window.XMLHttpRequest
    if (!this.requestPromise) {
        this.requestPromise = new Promise(resolve => {
            // ... perform request here, then call resolve() when done.
        });
    }
}

componentDidMount() {
    this.requestPromise.then(data => ...);
}

这将在componentWillMount 期间开始预加载您的请求,但该请求仅在componentDidMount 中处理,无论它到那时已经完成还是仍在进行中。

【讨论】:

    【解决方案3】:

    您应该在 componentDidMount 中发出请求,因为不应在 componentWillMount 中发出副作用请求。可以在componentWillMount中设置状态,如果在componentDidMount中设置状态,您将立即触发第二次重新渲染。

    你会读到它是一种反模式 (UGHHH),并且一些 linter 禁止它 (eslint-react-plugin),但我不会太在意这一点,因为有时它是与 DOM 交互的唯一方式.如果您使用关联的 babel 阶段,您可以在 willMount 或方法属性 ( state = { } ) 中设置默认状态

    正如您所说,组件已经被渲染一次,但这很好,因为您可以显示某种加载器或资源正在加载的任何其他形式的信息。

    class MyComp extends Component {
    
        // What I do with stage 0
        state = { mystate: 1 }
    
        // What you might want to do if you're not 
        // on the experimental stage, no need to do 
        // the whole constructor boilerplate
        componentWillMount() {
            this.setState({ mystate: 1 });
        }
    
        componentDidMount() {
            dispatch(yourAction());
    
            // It's fine to setState here if you need to access 
            // the rendered DOM, or alternatively you can use the ref
            // functions
        }
    
        render() {
            if (!this.props.myCollection) return <Loader />
    
            return (
               <div> // your data are loaded </div>
            )
        }
    }
    

    【讨论】:

      【解决方案4】:

      在 render 方法之前避免在生命周期钩子中获取的真正原因是因为 React 社区计划使 render 方法调用异步。

      在这里查看来自 gaeron 的回复:https://github.com/reactjs/reactjs.org/issues/302

      现在这意味着在渲染之前在任何生命周期方法中放置诸如 fetch(或任何异步操作)之类的异步操作会干扰渲染过程。

      与您今天想象的同步执行不同:

      1.构造函数 > => 2. getDerivedStateFromProps > => 3.渲染 => 4。 componentDidMount => 5. 回调按添加顺序执行,因此 fetch 回调现在运行。

      它会变成这样:

      1.构造函数 > => 2. getDerivedStateFromProps > > => 回调按照它们被添加的顺序执行3。所以 fetch 回调首先运行 => 4。渲染回调运行 => 5。 componentDidMount

      这种干扰可能会导致状态更改被还原,因为渲染可能会应用较早的状态来覆盖 fetch 所做的更改。

      另一个原因是 componentDidMount 生命周期保证了相应组件在 DOM 上的存在,如果 fetch 尝试在 DOM 可用或更新之前对其进行操作,则可能导致应用程序显示错误。

      【讨论】:

        猜你喜欢
        • 2015-09-03
        • 1970-01-01
        • 1970-01-01
        • 2019-10-15
        • 2020-12-27
        • 2014-12-24
        • 2011-09-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多