简体   繁体   English

功能组件中的新道具不会重新渲染

[英]New props in functional components does not re-render

I'm currently having a problem on my functional components that does not update when it receives new props.我目前在收到新道具时无法更新的功能组件出现问题。 I want to clarify my mental model and after looking at the cheat sheet from react website, new props should update the component if it is saved in the state right?我想澄清我的心理 model 并在查看 react 网站的 备忘单后,如果新道具保存在 state 中,则应该更新组件,对吗?

Consider the following code:考虑以下代码:

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,
};

The code above does not update the state when I updated both startDate and endDate .当我同时更新startDateendDate时,上面的代码不会更新 state 。 I have to call useEffect for it to sync.我必须调用useEffect才能同步。 I thought when we are receiving new props, a component should re-renders thus recalls useState to set it with the default value.我想当我们收到新的道具时,组件应该重新渲染,因此调用useState将其设置为默认值。

I want to know why do I have to add this code in order for it to work where I was expecting my component to update when I updated the props.我想知道为什么我必须添加此代码才能使其在我更新道具时期望我的组件更新的地方工作。 Code added:添加的代码:


  useEffect(() => {
  ┊ if (startDate && endDate) {
  ┊ ┊ handleEndDateChange(endDate);
  ┊ ┊ handleStartDateChange(startDate);
  ┊ }
  }, [startDate, endDate]);

IncidentList will re-render if any of it's props are updated.如果任何道具更新, IncidentList将重新渲染。

However, it doesn't seem like you are using startDate and endDate .但是,您似乎没有使用startDateendDate Instead, you're just setting the initial value of selectedStartDate and selectedEndDate , which is not part of the re-rendering, and thus selectedStartDate and selectedEndDate will not update when startDate and endDate update.相反,您只是设置selectedStartDateselectedEndDate的初始值,这不是重新渲染的一部分,因此当startDateendDate更新时selectedStartDateselectedEndDate不会更新。

try using startDate and endDate directly, unless you have some logic ( if (startDate && endDate) ??), in which case you'll need the state objects you added.尝试直接使用startDateendDate ,除非您有一些逻辑( if (startDate && endDate) ??),在这种情况下,您将需要您添加的 state 对象。

You need to pass props from parent's state.您需要从父母的 state 传递道具。

For example:例如:

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

In contrast, the following won't work:相反,以下内容将不起作用:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM