首页 > 解决方案 > 过滤后返回处于 React 状态的对象的正确长度

问题描述

我是 React 的新手,并且一直在开发这个功能,其中有一个过滤选项,用户在输入中键入他正在寻找的用户的姓名或电子邮件,并且列表会随着输入的变化而更新。

当组件加载时,useEffecthook 从我的 api 中获取数据并将返回设置为我的状态,并且在过滤器输入中键入的数据也保存在状态中。

我在打字时的过滤效果很好,filter旁边的map效果很好,并且只列出了我正在寻找的用户。

我的问题是,当组件加载时,它还会显示找到了多少用户,现在我只列出组件安装时的数组长度,所以我的问题是:

如何在users不破坏状态的情况下更新数组长度的大小?如果我在我的状态中设置过滤后的数组,并且在删除查询字符串后,我的状态将被破坏......我尝试使用过滤结果创建另一个状态但没有工作,还有另一种更好的方法或者我做错了什么?

<ContentSearchReturn section="Mentores" qtdUsers={users.length} />

在此处输入图像描述

Mentors呈现页面ListMentors的组件,并且是呈现我的每个 Evee 盒子的组件。

const Mentors = () => {
  const formRef = useRef(null);
  const [users, setUsers] = useState([]);
  const [filter, setFilter] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      const { data } = await api.get("/colaborador/mentores");

      setUsers(data);
    };

    fetchUsers();
  }, []);

  return (
    <Layout>
      <BodyContent
        header="Gerenciamento de Mentores"
        breadcrumb="Home > Mentores"
      >
        <Form ref={formRef} style={{ marginBottom: "3vh" }}>
          <Row>
            <Col lg="8" style={{ backgroundColor: "" }}>
              <FormGroup>
                <Input
                  label="Informe o nome ou e-mail do mentor"
                  name="pesquisa"
                  testid="fieldPesquisarColaborador"
                  style={{ marginTop: "0", marginBottom: "0" }}
                  onChange={(e) => setFilter(e.target.value)}
                />
              </FormGroup>
            </Col>

            <Col lg={{ size: 3, offset: 1 }} style={{ backgroundColor: "" }}>
              <Button
                text="Cadastrar"
                onClick={() => history.push("/admin/create-collaborator")}
                style={{ width: "100%" }}
              />
            </Col>
          </Row>
        </Form>
        <ListMentors users={users} filter={filter} />
      </BodyContent>
    </Layout>
  );
};

export default Mentors;

ListMentors组件并且qtdUsers是在上面打印中显示 7 个结果的道具。

const ListMentors = ({ users, filter }) => {
  return (
    <>
      <ContentSearchReturn section="Mentores" qtdUsers={users.length} />
      <Row>
        {users.length > 0 ? (
          users
            .filter((user) => {
              if (!filter) return true;
              if (user.nome.includes(filter) || user.email.includes(filter)) {
                return true;
              }
            })
            .map((user, index) => {
              return (
                <UserBox
                  key={index}
                  nome={user.nome}
                  cargo={user.nome_cargo}
                  departamento={user.nome_departamento}
                />
              );
            })
        ) : (
          <div>
            <h1>Ops! 0 resultados...</h1>
          </div>
        )}
      </Row>
    </>
  );
};

export default ListMentors;

非常感谢您的宝贵时间,并为我的英语感到抱歉,这里不是母语人士。

标签: javascriptarraysreactjsuse-state

解决方案


您可以使用useMemo来存储过滤后的用户数组。

然后filteredUser.length将始终是过滤后数组的大小(或整个数组的!filter大小true

请注意,派生值将仅在usersfilter更改时计算。

const ListMentors = ({users, filter}) => {
    const filteredUsers = useMemo(() => {
        return users.filter((user) => {
            if (!filter) return true;
            if (user.nome.includes(filter) || user.email.includes(filter)) {
                return true;
            }
        });
    }, [users, filter]);

    return (
        <>
            <ContentSearchReturn section="Mentores" qtdUsers={filteredUsers.length} />
            <Row>
                {filteredUsers.length > 0 ? (
                    filteredUsers.map((user, index) => {
                        return (
                            <UserBox
                                key={index}
                                nome={user.nome}
                                cargo={user.nome_cargo}
                                departamento={user.nome_departamento}
                            />
                        );
                    })
                ) : (
                    <div>
                        <h1>Ops! 0 resultados...</h1>
                    </div>
                )}
            </Row>
        </>
    );
};

export default ListMentors;

PS。

const filteredUsers = users.filter((user) => {
    if (!filter) return true;
    if (user.nome.includes(filter) || user.email.includes(filter)) {
        return true;
    }
});

不使用useMemo也应该可以正常工作,但它会导致您在每次渲染时重新计算过滤后的数组。


推荐阅读