skip to Main Content

How to filter data in both directions?

I have data that I receive from the server and store in the state, I need to filter it to open and close, but since I update the state I can only close it, but how can I then open it using only the state?

const data = [
  {
    id: 1,
    title: "Project 01",
    project_id: null,
    is_project: true,
  },
  {
    id: 2,
    title: "Task 01",
    project_id: 1,
    is_project: false,
  },
  {
    id: 3,
    title: "Task 02",
    project_id: 1,
    is_project: false,
  },
  {
    id: 4,
    title: "Project 02",
    project_id: null,
    is_project: true,
  },
  {
    id: 5,
    title: "Task 03",
    project_id: 4,
    is_project: false,
  },
];

const [state, setState] = useState([]);

  useEffect(() => {
    setState(data); // my fetch req
  }, []);

  const onVisible = (id) => {
    const filtered = state?.filter((el) => el?.project_id !== id);
    setState(filtered);
  };

enter image description here

When I click on +, the tasks disappear, but if I click on + again they will not appear again, since I am using a state, how can I make them appear again?

2

Answers


  1. import { useEffect, useState } from "react";
    import "./styles.css";
    
    const data = [
      {
        id: 1,
        title: "Project 01",
        project_id: null,
        is_project: true,
      },
      {
        id: 2,
        title: "Task 01",
        project_id: 1,
        is_project: false,
      },
      {
        id: 3,
        title: "Task 02",
        project_id: 1,
        is_project: false,
      },
      {
        id: 4,
        title: "Project 02",
        project_id: null,
        is_project: true,
      },
      {
        id: 5,
        title: "Task 03",
        project_id: 4,
        is_project: false,
      },
    ];
    
    export default function App() {
      const [state, setState] = useState([]);
    
      useEffect(() => {
        setState(data); // my fetch req
      }, []);
    
      const onVisible = (id) => {
        const filtered = state?.filter((el) => el?.project_id !== id);
        console.log(state, filtered);
        if (state.length == filtered.length) {
          setState(data);
        } else {
          setState(filtered);
        }
      };
      return (
        <div className="App">
          {state?.map((el) => (
            <div key={el.id} style={{ display: "flex", columnGap: 8 }}>
              {el?.is_project && <div onClick={() => onVisible(el?.id)}>+</div>}
              <div style={{ marginLeft: el?.is_project ? 0 : 24 }}>{el.title}</div>
            </div>
          ))}
        </div>
      );
    }
    
    
    

    this is a temporary solution , the whole mapping of the data part is a bit unclear .

    Login or Signup to reply.
  2. You will have to save whether the values are expanded or not. Let say if you can modify the data before storing it into response then you can introduce a new key called is_expanded to indicated whether to show it as expanded.

    import { useEffect, useState } from "react";
    import "./styles.css";
    
    const data = [
      {
        id: 1,
        title: "Project 01",
        project_id: null,
        is_project: true,
        is_expanded: true,
      },
      {
        id: 2,
        title: "Task 01",
        project_id: 1,
        is_project: false,
        is_expanded: true,
      },
      {
        id: 3,
        title: "Task 02",
        project_id: 1,
        is_project: false,
        is_expanded: true,
      },
      {
        id: 4,
        title: "Project 02",
        project_id: null,
        is_project: true,
        is_expanded: true,
      },
      {
        id: 5,
        title: "Task 03",
        project_id: 4,
        is_project: false,
        is_expanded: true,
      },
    ];
    
    export default function App() {
      const [state, setState] = useState([]);
    
      useEffect(() => {
        setState(data); // my fetch req
      }, []);
    
      const onVisible = (id) => {
        // const filtered = state?.filter((el) => el?.project_id !== id);
        setState((prevValue) => {
          const newValue = [];
          prevValue.forEach((value) => {
            if (value.id === id || value.project_id === id) {
              newValue.push({
                ...value,
                is_expanded: !value.is_expanded,
              });
            } else {
              newValue.push(value);
            }
          });
          return newValue;
        });
      };
      return (
        <div className="App">
          {state?.map((el) => (
            <div key={el.id} style={{ display: "flex", columnGap: 8 }}>
              {el?.is_project && (
                <div onClick={() => onVisible(el?.id)}>+ {el.title}</div>
              )}
              {!el?.is_project && el?.is_expanded && (
                <div style={{ marginLeft: el?.is_project ? 0 : 24 }}>
                  {el.title}
                </div>
              )}
            </div>
          ))}
        </div>
      );
    }
    
    

    Initially, all of them are expanded. Once you toggle any project, any value that is part of it or the project will be toggled.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search