【问题标题】:Calling useQuery conditionally results into build failures有条件地调用 useQuery 会导致构建失败
【发布时间】:2020-11-15 19:04:09
【问题描述】:

我有一个用例,我在 UI 中显示与用户关联的所有待办事项列表。有一个切换按钮,切换它,仅显示同一用户的 completed 待办事项列表。我正在调用 react hook useQuery有条件 基于切换按钮状态。下面是代码:

import TodoItems from './TodoItems';
import { LIST_TODOS_BY_USERNAME, LIST_TODOS_BY_STATUS } from '../graphql/queries';
import { useQuery } from '@apollo/react-hooks';

type TodoListProps = {
  username: string;
  showCompleted: boolean;
};

const TodoList:FC<TodoListProps> = ({ username, showCompleted }) => {
  const { loading, error, data } = !showCompleted
    ? useQuery(LIST_TODOS_BY_USERNAME, { variables: { username }, pollInterval: 500 })
    : useQuery(LIST_TODOS_BY_STATUS, { variables: { username, status: 'COMPLETED' }, pollInterval: 500 });

  if (error) {
    return (
      <div>
        <p>{`Error! ${error}`}</p>
      </div>
    );
  }

  return (
    <div className="todoapp">
      <div>
        <header className="header">
          <div className="imagetool">
            <img
              alt={username}
              src={`https://something.com/?uid=${username}`}
            />
          </div>
          <H1>
            {username}
            &rsquo;s todos
          </H1>
          <div className="todo-list-container">
            <Row gridGap={32} justifyContent="center" padding={8}>
              <View>
                {loading ? (
                  <Col alignItems="start" gridGap={16}>
                    <Spinner size={SpinnerSize.Small} />
                  </Col>
                ) : (
                  <TodoItems todoListItems={!showCompleted ? data.getTodosByUserName : data.getTodosByStatus} />
                )}
              </View>
            </Row>
          </div>
        </header>
      </div>
    </div>
  );
};

export default TodoList;

然而,这很好用,但在构建过程中,由于 linting 开始发挥作用,它失败并出现错误:

17:7 错误 React Hook "useQuery" 被有条件地调用。 React Hooks 必须在每个组件渲染中以完全相同的顺序调用 react-hooks/rules-of-hooks

如何在不禁用 lint 规则的情况下解决问题?

任何指针表示赞赏!

【问题讨论】:

    标签: javascript reactjs graphql react-hooks


    【解决方案1】:

    在 React 中,钩子需要总是被调用——因此它们应该只在某些时候被调用(=有条件地)。这甚至适用于使用相同钩子函数的钩子(useQuery() 与您的情况一样)。要在每个渲染迭代中调用非常相似useQuery(),请使用一个钩子;因此

    改变这个

      const { loading, error, data } = !showCompleted
        ? useQuery(LIST_TODOS_BY_USERNAME, { variables: { username }, pollInterval: 500 })
        : useQuery(LIST_TODOS_BY_STATUS, { variables: { username, status: 'COMPLETED' }, pollInterval: 500 });
    

    到这里:

      const { loading, error, data } = useQuery(
        !showCompleted ? LIST_TODOS_BY_USERNAME : LIST_TODOS_BY_STATUS,
        {
          variables: !showCompleted
            ? { username }
            : { username, status: 'COMPLETED' },
          pollInterval: 500,
        }
      )
    

    【讨论】:

      【解决方案2】:

      不要有条件地使用 useQuery。您有两种选择,要么将查询作为 prop 的值获取,要么将查询的名称存储在组件的状态中并根据需要进行更改。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-23
        • 1970-01-01
        • 1970-01-01
        • 2019-09-21
        • 1970-01-01
        • 2020-08-11
        相关资源
        最近更新 更多