useState 对象数组

IT技术 javascript reactjs ecmascript-6 react-hooks
2021-04-08 04:23:08

我有一个搜索框,可以从 Excel 中复制和粘贴一列。我解析输入并生成一个条目数组。

然后我映射条目并调用每个项目的自定义钩子以从我的graphql端点获取一些数据

例如:

搜索框中提供了 3 个条目:

["D38999/26", "LJT06RE25-61PA", "D38999/46FJ61AA"]

fetchData函数一次接收这些项目之一作为查询参数。目前,此过程将返回 3 个单独的对象,如下所示:

{query: "D38999/26", cables: Array(35)}
{query: "LJT06RE25-61PA", cables: Array(1)}
{query: "D38999/46FJ61AA", cables: Array(1)}

如何设置react-hooks以允许我将每个对象result作为对象数组附加到State 中?

我的最终目标是像这样的对象数组:

[
{query: "D38999/26", cables: Array(35)},
{query: "LJT06RE25-61PA", cables: Array(1)},
{query: "D38999/46FJ61AA", cables: Array(1)}
]

这是我当前用于解析 API 端点的自定义钩子

const useCableMatch = () => {
  const [result, setResult] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);
  const client = useApolloClient();

  const fetchData = async query => {
    setIsError(false);
    setIsLoading(true);
    try {
      const { data } = await client.query({
        query: GET_VALID_CABLE,
        variables: { pn: `%${query}%` },
      });

      const response = { query, ...data };
      console.log('response:', response);

      setResult(response);
    } catch (error) {
      setIsError(true);
    }
    setIsLoading(false);
  };

  return [{ result, isLoading, isError }, fetchData];
};

当前setResult设置为仅从响应中返回单个对象。我想返回一个数组,其中生成的每个对象都附加到现有的对象数组中。

2个回答

假设response可以直接添加到result数组中,则可以:

setResult(result => [...result, response]);

这将从response先前的result状态并使用array spread operator.

赞成。此外,如果您更新了一些深层的值result并需要重新渲染,您可以这样做setResult( result => [...result] )将其视为导致渲染的轻推
2021-06-07 04:23:08
谢谢你。当我使用.push()添加到现有状态数组并尝试将其设置为其状态时,我一直在为为什么我的子组件不会更新而苦苦挣扎它会工作,但我依赖于数组的子组件没有按预期立即重新渲染。(它将在随后的渲染或强制渲染中进行)。
2021-06-09 04:23:08
@JeremyLondon 用于设置状态是异步的。该符号确保使用result.
2021-06-14 04:23:08
这有效!我很好奇为什么 setResult(result => [...result, response]); 但这不是..setResult([...result, response]);
2021-06-20 04:23:08

您可以将整个数组传递给钩子并将结果作为数组返回。您还应该useEffect用于异步逻辑。我重写了您的代码以一次处理所有 3 个字段:

const useCableMatch = (searchInput) => {
  const [result, setResult] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);
  const client = useApolloClient();

  useEffect((searchInput) => {
     setIsError(false);
     setIsLoading(true);
     let response
     for(let field of searchInput){
        try {
           const { data } = await client.query({
              query: GET_VALID_CABLE,
              variables: { pn: `%${field}%` },
           });

           response = { ...data };
         } catch (error) {
             setIsError(true);
         }
     }
     setResult(current => {query, ...current, ...response);
     setIsLoading(false);
   };
  }, [searchInput])

  return [{ result, isLoading, isError }];
};