Krisna
Krisna

Reputation: 3423

JavaScript filter does not update the React local state

Description of the app

I am using Ant-transfer for my app. I have two components one is the parent and another is child component. In the child component, I am using the Ant-transfer, Without fetching any data when I play with local state, I can able to transfer the data from one table to another table. And it works as expected.

My case scenario is

I have one fixed data. Which contains arrays of objects. From that fixed data, I transfer item from the group table to the target table By using Ant-transfer. After pressing the transfer button(">") which is then called on handleChange function. After triggering the handleChange function, it updates the targetKey local state and does post request.

Issue

When an item or items are selected and a post request is made, I retrieve the selected items from the parent component. I filtered the fixed data from the selected items and passed the string id of the items array to the local state. However, when I refresh the page, the fixed data returns to its original state. All items are in the group table, and it does not show select items which should be on the right side of the table. It appears that my filtered function does not work.

Goal:

My goal is for selected items to be on the right side and unselected items to be on the left side; if I refresh the page, it should not change.

Reproduce the ant transfer

I reproduced Ant-transfer-demo.

This is my all code

const ZoneGroups: React.FC<Props> = ({
  onAddToZone,
  selectedDisplayGroups,
}) => {
  const displayGroups = [
    {
      id: "FF",
      level: 2,
      name: "rice",
    },
    {
      id: "AA",
      level: 2,
      name: "juice",
    },
    {
      id: "GAA",
      level: 2,
      name: "ball",
    },
    {
      id: "FF3AA",
      level: 2,
      name: "TV",
    },
    {
      id: "FH",
      level: 2,
      name: "Pencil",
    },
    {
      id: "FHAA",
      level: 2,
      name: "Tea",
    },
  ];

  // After post request I am getting updated selected group "selectedDisplayGroups"
  // "selectedDisplayGroups" data array of object like this: 👇🏾
  // [{
   //   id: "FHAA",
    //  level: 2,
    //  name: "Tea",
  //    }],

  
  const DisplayItems = displayGroups.map((displayGroup, index) => {
    return {
      key: displayGroup.id,
      title: `${displayGroup.level} ${displayGroup.name}`,
    };
  });
  
  
  const SelectedItems = selectedDisplayGroups.map(
    (displayGroup) => displayGroup.id
  );
  // This is the items id which is selected.👆🏽👆🏽👆🏽👆🏽
  // SelectedItems return array of string ID ['FH', 'FHAA', 'GA'] like this

  const filteredGroups = DisplayItems.filter((g) =>
    SelectedItems.includes(g.key)
  ).map((id) => id.key);

  console.log(SelectedItems);

  const [selectedIds, setSelectedIds] = useState([]);
  const [targetKey, setTargetKey] = useState(filteredGroups);
  const [submit, setSubmit] = useState(false);

  const handleChange = (target: string): void => {
    setTargetKey(target);
    onAddToZone(target); // this is my post request function
    setSubmit(true);
  };

  const handleSelectChange = (sourceSelectedKeys: string, id: string): void => {
    setSelectedIds([...sourceSelectedKeys]);
  };

  return (
    <>
      <Transfer
        dataSource={DisplayItems}
        titles={["Group", "Target"]}
        render={(item): string => item.title}
        targetKeys={targetKey}
        selectedKeys={selectedIds}
        onChange={handleChange}
        onSelectChange={handleSelectChange}
        showSearch
        oneWay
        checked={submit}
        style={{ marginBottom: 50 }}
      />
    </>
  );
};

export default ZoneGroups;

Upvotes: 3

Views: 567

Answers (1)

Drew Reese
Drew Reese

Reputation: 202864

If you need to persist any of the state to localStorage to allow reloading the app then it appears you should persist the targetKeys state.

Example:

const App = () => {
  // Lazy state initializer function to load from localStorage
  // or fallback/default initial value
  const [targetKeys, settargetKeys] = useState(() => {
    return JSON.parse(localStorage.getItem("targetKeys")) || filteredGroups;
  });
  const [selectedKeys, setselectedKeys] = useState([]);

  // persist state updates to localStorage
  useEffect(() => {
    localStorage.setItem("targetKeys", JSON.stringify(targetKeys));
  }, [targetKeys]);

  const handleChange = (nextTargetKeys) => {
    settargetKeys(nextTargetKeys);
  };

  const handleSelectChange = (sourceSelectedKeys) => {
    setselectedKeys([...sourceSelectedKeys]);
  };

  return (
    <>
      <Transfer
        dataSource={DisplayItems}
        titles={["Source", "Target"]}
        targetKeys={targetKeys}
        selectedKeys={selectedKeys}
        onChange={handleChange}
        onSelectChange={handleSelectChange}
        render={(item) => item.title}
        oneWay
        style={{ marginBottom: 16 }}
      />
    </>
  );
};

Edit javascript-filter-does-not-update-the-react-local-state

When the component mounts you'll very likely want to refetch any data from your DBs to ensure you've the latest backend data, but if you needed any of this data at app start/mount then persist any other data/state your app/component needs.

Upvotes: 1

Related Questions