【问题标题】:New props in functional components does not re-render功能组件中的新道具不会重新渲染
【发布时间】:2020-10-21 10:41:34
【问题描述】:

目前我的功能组件在收到新道具时没有更新。我想澄清我的心智模型,在查看 react 网站上的 cheat sheet 之后,如果新的道具保存在状态下,它应该更新组件吗?

考虑以下代码:

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

当我更新startDateendDate 时,上面的代码没有更新状态。我必须打电话给useEffect 才能同步。我想当我们收到新的道具时,组件应该重新渲染,因此调用useState 将其设置为默认值。

我想知道为什么我必须添加此代码才能使其在我更新道具时期望我的组件更新的地方工作。添加代码:


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

【问题讨论】:

  • useEffect 将在 [] 中的变量像旧版 componentWillUpdate 一样工作时运行。
  • 我知道,问题是为什么在我为它提供我用作默认状态的新道具后它不重新渲染@moficodes

标签: javascript reactjs


【解决方案1】:

你需要从父母的状态传递道具。

例如:

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

【讨论】:

    【解决方案2】:

    IncidentList 的任何道具更新后将重新渲染。

    但是,您似乎没有使用startDateendDate。相反,您只是设置了selectedStartDateselectedEndDate 的初始值,这不是重新渲染的一部分,因此selectedStartDateselectedEndDatestartDateendDate 更新时不会更新.

    尝试直接使用startDateendDate,除非你有一些逻辑(if (startDate &amp;&amp; endDate) ??),在这种情况下你需要你添加的状态对象。

    【讨论】:

    • 对不起,我实际上是在组件中使用它,我在组件中使用了selectedStartDateselectedEndDate。但是它没有更新...我应该直接使用道具吗?
    • 是的,只要它们来了就使用它们。 useState 用于创建本地状态对象,以及更新它的函数。如果你需要在组件的任何地方使用一个道具,你可以直接使用它。当它更新时,组件将更新。如果你在 useEffect 中使用它,useEffect 将运行(假设你将 prop 添加到依赖数组中)
    • 是的,你是对的,如果我直接使用了道具,那么它会重新渲染。我猜 useState 只是被称为构造函数......
    猜你喜欢
    • 2023-02-15
    • 2022-11-29
    • 2021-12-22
    • 2021-08-27
    • 1970-01-01
    • 2019-08-22
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多