简体   繁体   English

在 React.js 中,我应该在 componentWillMount 还是 componentDidMount 中进行初始网络请求?

[英]In React.js should I make my initial network request in componentWillMount or componentDidMount?

In the react docs it recommends making initial network requests in the componentDidMount method:在 react 文档中,它建议在componentDidMount方法中进行初始网络请求:

componentDidMount() is invoked immediately after a component is mounted. componentDidMount()在组件安装后立即调用。 Initialization that requires DOM nodes should go here.需要 DOM 节点的初始化应该在这里进行。 If you need to load data from a remote endpoint, this is a good place to instantiate the network request.如果您需要从远程端点加载数据,这是实例化网络请求的好地方。 Setting state in this method will trigger a re-rendering.在此方法中设置状态将触发重新渲染。

If componentWillMount is called before rendering the component, isn't it better to make the request and set the state here?如果componentWillMount被渲染组件之前调用,是不是更好,使请求,并在这里设置的状态? If I do so in componentDidMount , the component is rendered, the request is made, the state is changed, then the component is re-rendered.如果我在componentDidMount这样做,则呈现组件,发出请求,更改状态,然后重新呈现组件。 Why isn't it better to make the request before anything is rendered?为什么在呈现任何内容之前提出请求不是更好?

You should do requests in componentDidMount . 您应该在componentDidMount执行请求。

If componentWillMount is called before rendering the component, isn't it better to make the request and set the state here? 如果在渲染组件之前调用componentWillMount,那么在这里发出请求并设置状态不是更好吗?

No because the request won't finish by the time the component is rendered anyway. 不,因为无论如何,在组件呈现时请求都不会完成。

If I do so in componentDidMount, the component is rendered, the request is made, the state is changed, then the component is re-rendered. 如果我在componentDidMount中执行此操作,则会呈现组件,发出请求,更改状态,然后重新呈现组件。 Why isn't it better to make the request before anything is rendered? 为什么在呈现任何内容之前提出请求更好?

Because any network request is asynchronous . 因为任何网络请求都是异步的 You can't avoid a second render anyway unless you cached the data (and in this case you wouldn't need to fire the request at all). 除非你缓存了数据,否则无论如何都无法避免第二次渲染(在这种情况下,您根本不需要触发请求)。 You can't avoid a second render by firing it earlier. 通过先前触发它,你无法避免第二次渲染。 It won't help. 它无济于事。

In future versions of React we expect that componentWillMount will fire more than once in some cases, so you should use componentDidMount for network requests . 在React的未来版本中,我们希望componentWillMount在某些情况下会多次触发,因此您应该将componentDidMount用于网络请求

You should use componentDidMount . 您应该使用componentDidMount

Why isn't it better to make the request before anything is rendered? 为什么在呈现任何内容之前提出请求更好?

Because: 因为:

  • Your request will almost certainly not finish before the component is rendered (unless rendering large amounts of markup, or you are on a zero latency quantum entanglement connection) , and the component will ultimately need to re-render again, most of the time 您的请求几乎肯定不会在呈现组件之前完成(除非呈现大量标记,或者您处于零延迟量子纠缠连接) ,并且组件最终需要再次重新渲染,大多数情况下
  • componentWillMount is also called during server-side rendering (if applicable) 在服务器端呈现期间也调用componentWillMount (如果适用)

However, if you were to ask, isn't it better to initiate a request in componentWillMount (without actually handling it in place), I would definitely say yes (ES6), and I do this myself to occasionally cut a few milliseconds from load times: 但是,如果您要问,在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 => ...);
}

This will start preloading your request during componentWillMount , but the request is only handled in componentDidMount , whether it is already finished by then or still in progress. 这将在componentWillMount期间开始预加载您的请求,但请求仅在componentDidMount处理,无论是当时已完成还是仍在进行中。

You should make the request in componentDidMount as no side-effects requests should be made in componentWillMount. 您应该在componentDidMount中发出请求,因为不应在componentWillMount中进行副作用请求。 It's fine to setState in componentWillMount, if you setState in componentDidMount you will immediately trigger a second re-render. 可以在componentWillMount中设置setState,如果在componentDidMount中设置了state,则会立即触发第二次重新渲染。

You will read that it's an anti-pattern (UGHHH) and some linters have it prohibited (eslint-react-plugin), but I wouldn't pay huge attention to that as sometimes it's the only way to interact with the DOM. 你会读到它是一个反模式(UGHHH)并且一些短信禁止它(eslint-react-plugin),但是我不会非常注意它,因为有时它是与DOM交互的唯一方式。 You can set your default state either in willMount or as a method property ( state = { } ), if you're using the associated babel stage 您可以在willMount中设置默认状态,也可以在方法属性(state = {})中设置默认状态,如果您正在使用关联的babel阶段

As you say the component will be rendered already once, but this is good because you can display some kind of Loader or any other form of information that a resource is loading. 正如您所说,组件将只渲染一次,但这很好,因为您可以显示某种Loader或资源正在加载的任何其他形式的信息。

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

The real reason to avoid fetches in lifecycle hooks before the render method is because the React community is planning to make the render method calls asynchronous.在 render 方法之前避免在生命周期钩子中获取的真正原因是因为 React 社区计划使 render 方法调用异步。

Check the response from gaeron here : https://github.com/reactjs/reactjs.org/issues/302在此处查看 gaeron 的回复: https : //github.com/reactjs/reactjs.org/issues/302

Now this means placing an asynchronous action like fetch(or any asynchronous operation for that matter) in any of the lifecycle methods before render, will interfere with the rendering process.现在这意味着在渲染之前在任何生命周期方法中放置一个异步操作,如 fetch(或任何与此相关的异步操作),将干扰渲染过程。

So unlike the synchronous execution that you would imagine today :所以不像你今天想象的同步执行:

1. constructor << imagine firing fetch() here >> => 2. getDerivedStateFromProps << fetch completes, callback added to callback queue by event loop >> => 3. render => 4. componentDidMount => 5. callbacks executed in the order that they were added so fetch callback runs now. 1. 构造函数<< 想象在这里触发 fetch() >> => 2. getDerivedStateFromProps << fetch 完成,回调通过事件循环添加到回调队列 >> => 3. render => 4. componentDidMount => 5. 回调执行添加它们的顺序,以便获取回调现在运行。

it would instead be like this :它会是这样的:

1. constructor << imagine firing fetch() here >> => 2. getDerivedStateFromProps << in the meantime, fetch completes and callback gets queued >> << imagine firing async render() here. 1. 构造函数<< 想象在这里触发 fetch() >> => 2. getDerivedStateFromProps << 同时,获取完成并且回调被排队 >> << 想象在这里触发异步 render() 。 its callback too gets queued >> => callbacks get executed in the order that they were added 3. so fetch callback runs first => 4. render callback runs => 5. componentDidMount它的回调也被排队 >> => 回调按照它们添加的顺序执行3. 所以 fetch 回调首先运行=> 4. 渲染回调运行=> 5. componentDidMount

This interference may result in state changes getting reverted because render may apply an earlier state that overrides the changes made by fetch.这种干扰可能会导致状态更改被还原,因为渲染可能会应用一个较早的状态来覆盖由 fetch 所做的更改。

Another other reason being that fact that it is the componentDidMount lifecycle that guarantees the presence of the corresponding component on DOM and if fetch tries to manipulate the DOM even before its available or is updated, it could result in faulty application display.另一个原因是,componentDidMount 生命周期保证了相应组件在 DOM 上的存在,如果 fetch 尝试在 DOM 可用或更新之前对其进行操作,则可能导致应用程序显示错误。

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

相关问题 React.js 我可以在从 axios 请求返回的数组上的 componentDidMount() 中使用 array.map 吗? - React.js Can I use array.map within componentDidMount() on an array returned from an axios request? React.js 中的 componentWillMount 调用顺序 - Sequence of componentWillMount calls in React.js 在React中使用componentWillMount或componentDidMount生命周期函数进行异步请求 - Use componentWillMount or componentDidMount lifecycle functions for async request in React JQuery Promise在ComponentDidMount React.JS上失败 - JQuery Promise failing on ComponentDidMount React.JS componentDidMount 意外令牌错误 [React.js] - componentDidMount unexpected token error [React.js] 在React.js中使用componentWillMount等函数的目的是什么? - What is the purpose of having functions like componentWillMount in React.js? 使用componentWillmount React.Js渲染Json数据 - Render Json data using componentWillmount React.Js React.js 异步渲染:何时多次调用 componentWillMount - React.js async rendering: when componentWillMount will be called multiple times 为什么addChangeListener应该在componentDidMount而不是componentWillMount? - Why should addChangeListener be in componentDidMount instead of componentWillMount? 当我使用 React.js 在 Heroku 中使用 Axios 执行 GET 请求时,我应该使用哪个基础 url - Which base url should I use when I perform GET request with Axios in Heroku with React.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM