簡體   English   中英

在 React.js 中,我應該在 componentWillMount 還是 componentDidMount 中進行初始網絡請求?

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

在 react 文檔中,它建議在componentDidMount方法中進行初始網絡請求:

componentDidMount()在組件安裝后立即調用。 需要 DOM 節點的初始化應該在這里進行。 如果您需要從遠程端點加載數據,這是實例化網絡請求的好地方。 在此方法中設置狀態將觸發重新渲染。

如果componentWillMount被渲染組件之前調用,是不是更好,使請求,並在這里設置的狀態? 如果我在componentDidMount這樣做,則呈現組件,發出請求,更改狀態,然后重新呈現組件。 為什么在呈現任何內容之前提出請求不是更好?

您應該在componentDidMount執行請求。

如果在渲染組件之前調用componentWillMount,那么在這里發出請求並設置狀態不是更好嗎?

不,因為無論如何,在組件呈現時請求都不會完成。

如果我在componentDidMount中執行此操作,則會呈現組件,發出請求,更改狀態,然后重新呈現組件。 為什么在呈現任何內容之前提出請求更好?

因為任何網絡請求都是異步的 除非你緩存了數據,否則無論如何都無法避免第二次渲染(在這種情況下,您根本不需要觸發請求)。 通過先前觸發它,你無法避免第二次渲染。 它無濟於事。

在React的未來版本中,我們希望componentWillMount在某些情況下會多次觸發,因此您應該將componentDidMount用於網絡請求

您應該使用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處理,無論是當時已完成還是仍在進行中。

您應該在componentDidMount中發出請求,因為不應在componentWillMount中進行副作用請求。 可以在componentWillMount中設置setState,如果在componentDidMount中設置了state,則會立即觸發第二次重新渲染。

你會讀到它是一個反模式(UGHHH)並且一些短信禁止它(eslint-react-plugin),但是我不會非常注意它,因為有時它是與DOM交互的唯一方式。 您可以在willMount中設置默認狀態,也可以在方法屬性(state = {})中設置默認狀態,如果您正在使用關聯的babel階段

正如您所說,組件將只渲染一次,但這很好,因為您可以顯示某種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>
        )
    }
}

在 render 方法之前避免在生命周期鈎子中獲取的真正原因是因為 React 社區計划使 render 方法調用異步。

在此處查看 gaeron 的回復: https : //github.com/reactjs/reactjs.org/issues/302

現在這意味着在渲染之前在任何生命周期方法中放置一個異步操作,如 fetch(或任何與此相關的異步操作),將干擾渲染過程。

所以不像你今天想象的同步執行:

1. 構造函數<< 想象在這里觸發 fetch() >> => 2. getDerivedStateFromProps << fetch 完成,回調通過事件循環添加到回調隊列 >> => 3. render => 4. componentDidMount => 5. 回調執行添加它們的順序,以便獲取回調現在運行。

它會是這樣的:

1. 構造函數<< 想象在這里觸發 fetch() >> => 2. getDerivedStateFromProps << 同時,獲取完成並且回調被排隊 >> << 想象在這里觸發異步 render() 。 它的回調也被排隊 >> => 回調按照它們添加的順序執行3. 所以 fetch 回調首先運行=> 4. 渲染回調運行=> 5. componentDidMount

這種干擾可能會導致狀態更改被還原,因為渲染可能會應用一個較早的狀態來覆蓋由 fetch 所做的更改。

另一個原因是,componentDidMount 生命周期保證了相應組件在 DOM 上的存在,如果 fetch 嘗試在 DOM 可用或更新之前對其進行操作,則可能導致應用程序顯示錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM