【问题标题】:useLazyQuery results into "Too many re-renders"useLazyQuery 结果为“重新渲染过多”
【发布时间】:2020-06-13 19:32:49
【问题描述】:

我正在尝试Execute queries manually,因此遵循了 Apollo 官方文档。我看不出文档和我的代码之间有任何区别,但是,我总是收到错误“重新渲染太多”。

const FEED_QUERY = gql`
  query contactAccessKey($accessKey: String!) {
    contactAccessKey(accessKey: $accessKey) {
      id
      contactInformation
      belongsTo {
        id
        username
        email
      }
    }
  }
`;

function AccessKeySeeEmergencyContact() {
  const [contact, setContact] = useState("");
  const [getContactInformation, { loading, data }] = useLazyQuery(FEED_QUERY);

  if (loading) return <p>Loading ...</p>;

  if (data && data.contactAccessKey) {
    setContact(data.contactAccessKey);
  }

  const accessKeyCode = "34a60667-80e3-4c97-9ded-15875d6507b1";

  return (
    <div>
      {contact && <div>{contact.contactInformation}</div>}
      <button
        onClick={() =>
          getContactInformation({ variables: { accessKey: accessKeyCode } })
        }
      >
        Click me!
      </button>
    </div>
  );
}

export default AccessKeySeeEmergencyContact;

【问题讨论】:

  • 你在render中设置一个状态变量,把它移到useEffect
  • 我只是想知道为什么它适用于文档还是我错过了那里的任何东西?
  • 组件中甚至不需要设置状态,不知道那里发生了什么

标签: reactjs graphql react-apollo apollo-client graphene-django


【解决方案1】:

糟糕的 Apollo 示例!

const [contact, setContact] = useState("");
const [getContactInformation, { loading, data }] = useLazyQuery(FEED_QUERY);

if (loading) return <p>Loading ...</p>;

// additional condition to avoid endless rerendering
if (!contact && data && data.contactAccessKey) {
  setContact(data.contactAccessKey);
}

不需要使用状态(即使有条件强制额外重新渲染) - 您可以直接从 data 读取数据(它只是一个私有变量):

return (
  <div>
    {data && <div>{data.contactInformation}</div>}

【讨论】:

  • if (!contact ... setContact 在数据加载时创建一次运行块...您也可以使用onCompleted 处理程序...或将数据传递给有条件渲染的子组件(在子组件中转换/操作)。跨度>
  • 渲染多少后没有优化?因为 1 个在挂载时渲染,另一个在加载时设置为 false,另一个在我们将数据填充到已完成状态时进行
  • @HamzaKhattabi 这是一种“已完成”,您可以使用 onCompleted 处理程序 f.e.转换接收到的数据(如果成本很高,则使用状态是有意义的,否则在渲染期间使用转换) - 使用它会比那些条件更智能......通过直接使用data,您只能有 2 个渲染(对于useQuery)和 3 代表 useLazyQuery - 在状态中保存数据总是添加下一个渲染并且需要额外的 [条件] 代码
【解决方案2】:

useApolloClient 具有返回 Promise 的函数,我通过使用它解决了类似的问题。 请注意,我刚刚复制并编辑了您的代码,可能存在一些语法错误。一切顺利。

import { useApolloClient } from '@apollo/client';

function AccessKeySeeEmergencyContact() {
    const [contact, setContact] = useState('');
    const client = useApolloClient(); // this gives an ApolloClient    

    const accessKeyCode = '34a60667-80e3-4c97-9ded-15875d6507b1';

    return (
        <div>
            {contact && <div>{contact.contactInformation}</div>}
            <button
                onClick={async () => {
                    const { data } = await client.query({
                        query: FEED_QUERY,
                        variables: { accessKey: accessKeyCode },
                    });
                    console.log(data);
                }}>
                Click me!
            </button>
        </div>
    );
}

export default AccessKeySeeEmergencyContact;

【讨论】:

    猜你喜欢
    • 2020-08-06
    • 2020-01-07
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2021-08-04
    相关资源
    最近更新 更多