簡體   English   中英

基於道具的初始 state 在 React 中總是不好的嗎?

[英]Is initial state based on props always bad in React?

React 的一個常見知識是,如果我們不使它們同步,則由 props 初始化 state 是不好的。 這被認為很好:

import { useState, useEffect } from 'react';

export default function MyInput({ initialValue }) {
    const [value, setValue] = useState(initialValue);

    useEffect(
        () => setValue(initialValue),
        [initialValue]
    );

    return (
        <>
            <h1>The value is {value}</h1>
            <input
                type="text"
                value={value}
                onChange={event => setValue(event.target.value)}
            />
        </>
    );
}

但是,如果我實際上不想在initialValue更改時更新值並想在此處刪除useEffect()怎么辦? 它強烈反對 React 哲學嗎? 這對我來說很有意義,因為我實際上不想在其他東西更改作為initialValue傳遞的值時更新此輸入值。 我不希望用戶在發生這種情況時丟失他們的輸入。

有多糟糕?

本質上,使用 prop 作為 state 變量 AFAIK 的初始值並沒有錯。

但是,在您的示例中,您正在做一些荒謬的事情:您正在定義一個 state 變量,該變量使用道具的值進行初始化,然后每次道具更新時,您都會使用相同的值更新您的 state 。 不管它是否是反模式,它都沒有意義 - 直接使用 prop,你正在做無利可圖的額外工作。 如果您刪除useEffect ,您將非常有效地使用 prop 作為 state 變量的初始值。

在 React.js 中使用派生 state 的問題經常被誤解, 這個 StackOverflow 問題證明了這一點。

在問題提供的代碼示例中,不清楚為什么在可以直接使用initialValue道具時使用派生的 state。 為了清楚起見,為此目的使用useEffect將被視為反模式。 相反,您應該自己檢查更改,如React 文檔中所示

但是,如果EmailInput組件對initialValue做了一些修改,如果我們遵循“提升 state 的規則” (我相信作者試圖在此評論中解釋),這樣的邏輯將不必要地污染父組件。

在這種情況下,我認為如果謹慎使用,反模式可能是一個可以接受的選擇。 使用上述反模式的Robin Wieruch 博客文章

另一種解決方案是使用key屬性( 在這種情況下很有用),但這僅在 key 和initialValue基於不同狀態時才有效。 否則,可能會導致重復渲染。

具有key屬性的示例

// EmailInput.jsx
export default function EmailInput({ initialValue, onChange }) {
    const [value, setValue] = useState(initialValue);

    const handleChange = (event) => {
        const newValue = event.target.value;
        // do some modification on the newValue
        setValue(newValue);
        onChange(newValue); // pass value to parent
    };

    return (
        <>
            <h1>The Email is {value}</h1>
            <input type="text" value={value} onChange={handleChange} />
        </>
    );
}
// Checkout.jsx
export function Checkout() {
    const [user, setUser] = useState({
        id: 1,
        email: "example@example.com",
    });
    return (
        <>
            <EmailInput
                initialValue={user.email}
                key={user.id}
                onChange={(value) => setUser({ id: user.id, email: value })}
            />
            <button
                onClick={() => setUser({id: 2, email: "foo@bar.com"})}
            >
                Update user
            </button>
        </>
    );
}

暫無
暫無

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

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