[英]New props in functional components does not re-render
我目前在收到新道具時無法更新的功能組件出現問題。 我想澄清我的心理 model 並在查看 react 網站的 備忘單后,如果新道具保存在 state 中,則應該更新組件,對嗎?
考慮以下代碼:
const defaultStart = dayjs().startOf("month").format("YYYY-MM-DD");
const defaultEnd = dayjs().endOf("month").format("YYYY-MM-DD");
function IncidentList({
incidentsList,
requestIncidents,
selectedLoc,
selectedLoc,
startDate = defaultStart,
endDate = defaultEnd,
}) {
const [selectedEndDate, handleEndDateChange] = useState(endDate);
const [selectedStartDate, handleStartDateChange] = useState(startDate);
useEffect(() => {
┊ const payload = {
┊ ┊ location: selectedLoc,
┊ ┊ start_date: dayjs(selectedStartDate).format("YYYY-MM-DD"),
┊ ┊ end_date: dayjs(selectedEndDate).format("YYYY-MM-DD"),
┊ };
┊ requestIncidents(payload);
}, [requestIncidents, selectedEndDate, selectedStartDate]);
return (
┊ <div className="container sm:p-8 md:p-16">
┊ ┊ <MaterialTable
┊ ┊ ┊ columns={columns}
┊ ┊ ┊ data={incidentsList}
┊ ┊ ┊ title="Incident list"
┊ ┊ ┊ actions={actions}
┊ ┊ ┊ options={{
┊ ┊ ┊ ┊ pageSize: 20,
┊ ┊ ┊ }}
┊ ┊ ┊ components={{
┊ ┊ ┊ ┊ Toolbar: (props) => (
┊ ┊ ┊ ┊ ┊ <div className="p-8">
┊ ┊ ┊ ┊ ┊ ┊ <MTableToolbar {...props} />
┊ ┊ ┊ ┊ ┊ ┊ <div className="ml-8 p-8 border-1 w-1/2">
┊ ┊ ┊ ┊ ┊ ┊ ┊ <div className="flex flex-row">
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ <p className="text-lg font-semibold">Filter Using:</p>
┊ ┊ ┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ┊ ┊ ┊ <div className="flex flex-row -mx-4">
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ <div className="px-8">
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ <DatePicker
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ format="YYYY-MM-DD"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ label="Minimum Date"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ inputVariant="outlined"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ minDate={new Date("2015-01-01")}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ maxDate={dayjs().format()}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ value={selectedStartDate}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ onChange={handleStartDateChange}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ />
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ <div className="px-8">
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ <DatePicker
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ format="YYYY-MM-DD"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ label="Maximum Date"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ inputVariant="outlined"
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ minDate={selectedStartDate}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ maxDate={dayjs().format()}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ value={selectedEndDate}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ onChange={handleEndDateChange}
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ />
┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ┊ </div>
┊ ┊ ┊ ┊ ),
┊ ┊ ┊ }} />
const mapStateToProps = (state) => ({
incidentsList: state.incident.incidents,
selectedLoc: state.loc.selectedLoc,
});
IncidentList.propTypes = {
incidentsList: PropTypes.arrayOf(PropTypes.object),
requestIncidents: PropTypes.func,
selectedLoc: PropTypes.number,
endDate: PropTypes.string,
startDate: PropTypes.string,
};
當我同時更新startDate
和endDate
時,上面的代碼不會更新 state 。 我必須調用useEffect
才能同步。 我想當我們收到新的道具時,組件應該重新渲染,因此調用useState
將其設置為默認值。
我想知道為什么我必須添加此代碼才能使其在我更新道具時期望我的組件更新的地方工作。 添加的代碼:
useEffect(() => {
┊ if (startDate && endDate) {
┊ ┊ handleEndDateChange(endDate);
┊ ┊ handleStartDateChange(startDate);
┊ }
}, [startDate, endDate]);
如果任何道具更新, IncidentList
將重新渲染。
但是,您似乎沒有使用startDate
和endDate
。 相反,您只是設置selectedStartDate
和selectedEndDate
的初始值,這不是重新渲染的一部分,因此當startDate
和endDate
更新時selectedStartDate
和selectedEndDate
不會更新。
嘗試直接使用startDate
和endDate
,除非您有一些邏輯( if (startDate && endDate)
??),在這種情況下,您將需要您添加的 state 對象。
您需要從父母的 state 傳遞道具。
例如:
import React from 'react';
import IncidentList from './IncidentList';
const IncidentListContainer = () => {
const [startDate, setStartDate] = React.useState(new Date);
const [endDate, setEndDate] = React.useState(new Date);
setStartDate(newDate); // this will update child
return (
<IncidentList
startDate={startDate}
endDate={endDate}
// other props
/>
);
}
相反,以下內容將不起作用:
const startDate = new Date;
const endDate = new Date;
changeDatesLater(startDate, endDate); // this won't work
const IncidentListContainer = () => {
return (
<IncidentList
startDate={startDate}
endDate={endDate}
// other props
/>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.