【问题标题】:Return the correct length of a object in React's state after filtering it过滤后返回处于 React 状态的对象的正确长度
【发布时间】:2021-09-15 08:49:42
【问题描述】:

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

当组件加载时,useEffect hook 从我的 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;

非常感谢您抽出宝贵的时间,也很抱歉我的英语不是母语人士。

【问题讨论】:

    标签: javascript arrays reactjs use-state


    【解决方案1】:

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

    那么filteredUser.length 将始终是过滤后数组的大小(或者当!filtertrue 时为整个数组)

    请注意,仅当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 也可以正常工作,但它会导致您在每次渲染时重新计算过滤后的数组。

    【讨论】:

    • 非常感谢!很好的解决了我的问题!我现在就深入研究 useMemo !!再次感谢 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 2020-10-22
    • 2021-06-27
    • 2017-10-07
    • 1970-01-01
    • 2020-07-23
    • 2020-10-21
    相关资源
    最近更新 更多