Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

96
Visualizações
Store copy of data state before applying and after clearing filter

I have a simple app that calls an API, returns the data (as an array of objects), sets a data state, and populates a few charts and graphs.

const loadData = async () => {
    const url = 'https://my-api/api/my-api';
    const response = await fetch(url);
    const result = await response.json();

    setData(result.data);
}

After setting the data, the data state is sent to every component and everything is populated. I created a filters pane that can filter the existing, populated data (for example, a gender filter that filters the data on the selected gender). What I did, and it's obviously wrong, is created an onChange handler that filters the data to the selected gender then uses the setData (sent as a prop; also the state variable, data) to set the filtered data. When I clear the filter, the original, non-filtered data is replaced by the filtered data so the original data is lost.

const genderFilterHanlder = (e) => {
    const filteredData = data.filter(x => x.gender === e.target.value);
    setData(filteredData);
}

I tried creating an intermediary state the preserves the original data then upon clearing the filters, it sets the data (setData) to the original. But this breaks when I have a filter that allows you to choose multiple values (like multiple languages; I can choose one language, clear it successfully, but if I choose two languages, then clear one, it breaks as the data is now the first chosen filter data).

How would I go about this?

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

I'd leave data itself alone and have a separate filteredData state member that you set using an effect:

const [filteredData, setFilteredData] = useState(data);
const [filter, setFilter] = useState("");
// ...
useEffect(() => {
    const filteredData = filter ? data.filter(/*...apply filter...*/) : data;
    setFilteredData(filteredData);
}, [filter, data]); // <=== Note our dependencies
// ...
// ...render `filteredData`, not `data`...

Then your change handler just updates filter (setFilter(/*...the filter...*/)).

That way, any time the filter changes, or any time data changes, the data gets filtered and rendered.

Live Example:

const { useState, useEffect } = React;

const Child = ({data}) => {
    const [filteredData, setFilteredData] = useState(data);
    const [filter, setFilter] = useState("");

    useEffect(() => {
        if (!filter) {
            setFilteredData(data);
            return;
        }
        const lc = filter.toLocaleLowerCase();
        const filteredData = filter
            ? data.filter(element => element.toLocaleLowerCase().includes(lc))
            : data;
        setFilteredData(filteredData);
    }, [filter, data]); // <=== Note our dependencies
    
    return <div>
        <input type="text" value={filter} onChange={({currentTarget: {value}}) => setFilter(value)} />
        <ul>
            {filteredData.map(element => <li key={element}>{element}</li>)}
        </ul>
    </div>;
};

const greek = [
    "alpha",
    "beta",
    "gamma",
    "delta",
    "epsilon",
    "zeta",
    "eta",
    "theta",
    "iota",
    "kappa",
    "lambda",
    "mu",
    "nu",
    "xi",
    "omicron",
    "pi",
    "rho",
    "sigma",
    "tau",
    "upsilon",
    "phi",
    "chi",
    "psi",
    "omega",
];
const initialData = greek.slice(0, 4);
const Example = () => {
    const [data, setData] = useState(initialData);

    useEffect(() => {
        const handle = setInterval(() => {
            setData(data => {
                if (data.length < greek.length) {
                    return [...data, greek[data.length]];
                }
                clearInterval(handle);
                return data;
            });
        }, 800);
        return () => {
            clearInterval(handle);
        };
    }, []);

    return <Child data={data} />;
};

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

about 4 years ago · Juan Pablo Isaza Relatório

0

You need to have two states in your case. You can follow below example.

  const data = [
    { id: 1, name: "Mahela" },
    { id: 2, name: "Sangakkara" },
    { id: 3, name: "Dilshan" },
    { id: 4, name: "Malinga" },
    { id: 5, name: "Rangana" },
    { id: 6, name: "Kulasekara" }
  ];

  const [inputValue, setInputValue] = useState("");
  const [filtered, setFiltered] = useState([]);

  const inputChangeHandler = (e) => {
    setInputValue(e.target.value);
    setFiltered(data.filter((item) => item.name === e.target.value));
  };

  return (
    <div className="App">
      <input type="text" value={inputValue} onChange={inputChangeHandler} />
      {filtered.length > 0 && filtered.map((item) => <p>{item.name}</p>)}
      {filtered.length === 0 && data.map((item) => <p>{item.name}</p>)}
    </div>
  );

Here I have used constant for data array. You can use your data state. Don't replace data state with new data instead use second state for the filtered data.

about 4 years ago · Juan Pablo Isaza Relatório

0

dont change your state after filtering . hold your original data and get a copy of it in a variable and do your stuff on it like filtering. then use that variable for rendering the filtered data and if you want to clear the input or anything you can use your original state that you have been storing.

const FilterData = () => {
  const [data, setData] = useState([]);
  const [select, setSelect] = useState();

  const loadData = async () => {
    const url = "https://my-api/api/my-api";
    const response = await fetch(url);
    const result = await response.json();

    setData(result.data);
  };

  const filteredData = data.filter((item) => {
    if (!select) return null;
    return item.gender !== select;
  });

  return (
    <div>
      <select>...</select>
      {filteredData.map(...)}
    </div>
  );
};
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda