簡體   English   中英

React - 將 state 作為道具傳遞,不會導致子組件重新渲染

[英]React - Passing state as props not causing re-render on child component

我有一個啟動 state 的父組件,然后在安裝后根據獲取請求的結果更新它

const [vehicles, handleVehicles] = useState([])

    useEffect(() => {
        const token = localStorage.getItem('token')
        axios({
            //get data from backend
        }).then(({data}) => {
            handleVehicles(prevState => [...prevState, data])
        }).catch((err) => console.log(err))
    }, [])

我將 state 作為道具傳遞到子組件中。 在我的子組件中,我運行檢查以查看車輛數組是否已填充...如果是,我返回一些 jsx,否則我什么也不返回。 我的問題是 state 更改不會反映在傳遞的道具中並導致重新渲染。 除非我刷新頁面,否則它會保留在一個空數組中。

我通過

<RenderTableData vehicles={vehicles} />

我的子組件是:

const RenderTableData = (props) => {

    if (!props.vehicles[0]) {
        return null
    } else {
        return (
            props.vehicles[0].map((vehicle) => {
                return (
                    <tr key={vehicle._id}>
                        <td>{vehicle.name}</td>
                        <td>{vehicle._id}</td>
                        <td><button className="has-background-warning">Edit</button></td>
                        <td><button className="has-background-danger">Remove</button></td>
                    </tr>
                )
            })
        )
    }
}

我將如何解決這個問題?

編輯- 它實際上是按原樣工作的......由於某種原因,http 請求需要一段時間才能返回數據(而且我從來沒有足夠的耐心注意到)......所以我現在有一個新問題:(

我不知道prevState到底是什么,但我認為您的問題是由將 function 而不是新值傳遞給handleVehicles引起的。 所以你的代碼應該是:

    const [vehicles, handleVehicles] = useState([])

    useEffect(() => {
        const token = localStorage.getItem('token')
        axios({
            //get data from backend
        }).then(({data}) => {
            handleVehicles([...prevState, data])
        }).catch((err) => console.log(err))
    }, [])

為什么您在 object 上使用 map function。 您的子組件應如下所示:

const RenderTableData = (props) => {

if (!props.vehicles[0]) {
    return null
} else {
    return (
        props.vehicles.map((vehicle) => {
            return (
                <tr key={vehicle._id}>
                    <td>{vehicle.name}</td>
                    <td>{vehicle._id}</td>
                    <td><button className="has-background-warning">Edit</button></td>
                    <td><button className="has-background-danger">Remove</button></td>
                </tr>
            )
        })
    )
}

}

我在CodeSandbox寫了一個工作示例。 一些評論:

在組件安裝后,您的效果將只運行一次。 如果 API 返回成功,則會使用之前的列表創建新的車輛列表。 但是prevState是空的,所以在這種情況下,這與handleVehicles(data)相同。 如果您想在車輛列表中傳播數據,請不要忘記handleVehicles(prevState => [...prevState, ...data ]);

useEffect(() => {
    const token = localStorage.getItem('token')
    axios({
        //get data from backend
    }).then(({data}) => {
        handleVehicles(prevState => [...prevState, data])
    }).catch((err) => console.log(err))
}, [])

在您的子組件中,您可能希望 map 超過車輛列表,而不是第一個元素。 所以,你應該刪除[0]

const RenderTableData = (props) => {
    if (!props.vehicles[0]) {
        return null
    } else {
        return (
            props.vehicles[0].map((vehicle) => {
                return (
                    ...
                )
            })
        )
    }
}

暫無
暫無

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

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