0

Problem: react view is not updated

I have a state that has the following composition:

[
  {
    date: "12/10/2022",
    data: [
      { id: "1", title_tax: "tax number one" },
      { id: "2", title_tax: "tax number two" },
    ],
  },
  {
    date: "13/10/2022",
    data: [{ id: "3", title_tax: "tax number three" }],
  },
];

the data object is an array that stores more objects, this is usually where we add more items. The process of adding items to the context is fine and they are added correctly, but the user view does not update these new items.

In my component I have an array (cardsHistory) that basically receives the state I showed and then creates the visualization. I don't have any exceptions or anything, I'm just looking for a way to fix this.

interface IProps {
  cardsHistory: IPropsHistoryCard[];
  loadMoreHistories: () => void;
  isData: boolean;
}

function ScrollHistory({ cardsHistory, loadMoreHistories, isData }: IProps) {
  const histories: IPropsHistoryCard[] = cardsHistory;
  console.log(histories);
  return (
    <InfiniteScroll pageStart={1} loadMore={loadMoreHistories} hasMore={isData}>
      {histories && histories?.length > 0 ? (
        histories.map((x: IPropsHistoryCard) => (
          <HistoryCard key={x.date} date={x.date} data={x.data} />
        ))
      ) : (
        <Typography>No history to display</Typography>
      )}
    </InfiniteScroll>
  );
}

export default ScrollHistory;

just in case when i recieve a new item I'm using immer produce from immer

case DashboardActionTypes.addHistory:
      return produce(state, (draft) => {
        const newElement: IProcess = payload;
        const dayIncluded = new Date(
          newElement.startDateTime,
        ).toLocaleDateString();

        const processElement: IProcess[] = [];
        processElement.push(newElement);

        if (draft.history.length === 0) {
          const historyElement: IPropsHistoryCard = {
            date: dayIncluded,
            data: processElement,
          };
          draft.history.push(historyElement);
        } else {
          const index = draft.history
            .map((object) => object.date)
            .indexOf(dayIncluded);
          if (index < 0) {
            const historyElement: IPropsHistoryCard = {
              date: dayIncluded,
              data: processElement,
            };
            draft.history.push(historyElement);
          } else {
            const isInArray = draft.history[index].data.find(
              (element) => element.id === newElement.id,
            );
            if (isInArray === undefined)
              draft.history[index].data.push(newElement);
          }
        }
      });
Newbie
  • 4,462
  • 11
  • 23
CoolLife
  • 1,419
  • 4
  • 17
  • 43

1 Answers1

2

React does not perform a deep-check on the props, but just a shallow one. So if the outher most object does not change React will bail out from re-rendering your component.

Any state update in react must change the outher most object to be effective so you cannot apped to the array, you have to replace it with a new one.

newArray = [...oldArray, newItem]

I avoid strange side effets in React all object shall be immutable, therefore do not mutate objects (unless they are explicitly not meant to affect a component rendering).

There are some helpers available to deal with it.

Newbie
  • 4,462
  • 11
  • 23
  • thanks I understand the concept, I checked it but I'm using immer that produces a new state every time I change the current one, in theory it should be almost the same. – CoolLife Nov 13 '22 at 17:57
  • I see, I edited your question to disambiguate. Silly question, have you checked there are no duplicate keys, they may lead to strange rendering behaviours? Furthermore you are discussing about the `data` field so we need code for the `HistoryCard` component. – Newbie Nov 13 '22 at 20:41