Javascript 第一次尝试时,react查询中的筛选器工作不正常

Javascript 第一次尝试时,react查询中的筛选器工作不正常,javascript,reactjs,react-query,Javascript,Reactjs,React Query,我试图使用过滤器从数组中仅获取雌性,但在第一次尝试时,react query返回整个数组,之后它工作正常。知道我必须添加或删除什么属性,这样副作用就消失了。 这是我的密码: import React, { useState } from "react"; import { useQuery } from "react-query"; import getPersonsInfo from "../api/personCalls"; ex

我试图使用过滤器从数组中仅获取雌性,但在第一次尝试时,react query返回整个数组,之后它工作正常。知道我必须添加或删除什么属性,这样副作用就消失了。 这是我的密码:

import React, { useState } from "react";
import { useQuery } from "react-query";
import getPersonsInfo from "../api/personCalls";

export default function Persons() {
  const [persons, setPersons] = useState([]);
  const { data: personData, status } = useQuery("personsData", getPersonsInfo, {
    onSuccess: (data) => {
      setPersons(data.data);
    },
    onError: (error) => {
      console.log(error);
    }
  });

  const getFemaleOnlyHandler = () => {
    const result = personData.data.filter(
      (person) => person.gender === "female"
    );
    setPersons(result);
  };

  return (
    <>
      <button onClick={getFemaleOnlyHandler}>Female only</button>
      {status === "loading" ? (
        <div>Loading ... </div>
      ) : (
        <div>
          {persons.map((person) => (
            <div>
              <p>{person.name}</p>
              <p>{person.lastName}</p>
              <p>{person.address}</p>
              <p>{person.gender}</p>
              <p>{person.country}</p>
              <p>{person.city}</p>
            </div>
          ))}
        </div>
      )}
    </>
  );
}
import React,{useState}来自“React”;
从“react query”导入{useQuery};
从“./api/personCalls”导入getPersonsInfo;
导出默认功能人员(){
const[persons,setPersons]=useState([]);
const{data:personData,status}=useQuery(“personsData”,getPersonsInfo{
onSuccess:(数据)=>{
setPersons(data.data);
},
onError:(错误)=>{
console.log(错误);
}
});
const getFemaleOnlyHandler=()=>{
常量结果=personData.data.filter(
(person)=>person.gender==“女性”
);
设置人员(结果);
};
返回(
仅限女性
{状态===“正在加载”(
加载。。。
) : (
{persons.map((person)=>(
{person.name}

{person.lastName}

{个人地址}

{个人性别}

{个人.国家}

{个人.城市}

))} )} ); }

我在代码沙盒中添加了完整的代码:

我不完全熟悉
react query
,但是问题很可能是每次组件更新时都会重新获取(异步!)。由于
setPersons()
触发更新(即设置状态),它将更新新的
persons
状态,使其成为过滤后的女性列表,然后再次触发对所有人员的提取,该提取返回并将
persons
状态设置回完整列表(即,查看当您单击阴过滤器按钮,然后离开它时会发生什么情况)

在React中有一种更惯用的方法来实现这一点,即保持“单一真实来源”(即所有人),并根据某些本地ui状态动态过滤

例如,见下文,其中
数据
成为真相的来源,而
人员
是该真相来源的计算值。这样做的好处是,如果原始
数据
发生更改,则无需手动(读:强制)将其更新为仅限女性。这是“单向数据流”,并且“反应性”是人们经常谈论的话题,老实说,它是人们做出反应的原因

const{data={data:[]},status}=useQuery(
“个人数据”,
getPersonsInfo,
{
onSuccess:(数据)=>{},
onError:(错误)=>{
console.log(错误);
}
}
);
const[doFilterFemale,setFilterFemale]=useState(false);
const persons=doFilterFemale
?data.data.filter((person)=>person.gender==“女性”)
:data.data;


这是ofc,假设您总是从json文件加载。在实际的应用程序设置中,如果您控制后端,我总是建议在服务器端实现过滤、排序和分页,否则您将被迫在客户端上过度获取数据。

我认为您犯了从react query复制数据的错误其思想是react query是状态管理器,因此react query返回的数据就是您真正需要的全部数据

您在codesandbox中遇到的可能只是
refetchOnWindowFocus
。因此,您可以聚焦窗口并单击按钮,react query将执行后台更新并覆盖您的本地状态。这是我刚才提到的“复制”的直接结果

您要做的是存储用户选择,并动态计算所有其他内容,如下所示:

const [femalesOnly, setFemalesOnly] = React.useState(false)
const { data: personData, status } = useQuery("personsData", getPersonsInfo, {
    onError: (error) => {
        console.log(error);
    }
});

const getFemaleOnlyHandler = () => {
    setFemalesOnly(true)
};

const persons = femalesOnly ? personData.data.filter(person => person.gender === "female") : personData.data

然后,您可以显示
persons
中的所有内容,这些内容将始终是最新的,即使后台更新会产生更多的人员。如果计算(过滤)成本很高,您也可以使用
usemo
来对其进行记忆(仅当
personData
femalesOnly
更改时计算它-但这可能是过早的优化。

我明白了,所以我刚刚添加了refetchOnWindowFocus:false,它工作正常。但我不确定这样做是否正确。不,不是。您不应该将数据复制到本地状态。可能还有其他方法此处react查询将进行后台更新,在这种情况下,您的数据将再次被覆盖:)