【问题标题】:useLazyQuery causing too many re-renders [Apollo/ apollo/react hooks]useLazyQuery 导致过多的重新渲染 [Apollo/apollo/react hooks]
【发布时间】:2020-01-07 02:57:58
【问题描述】:

我正在构建一个不和谐/松弛克隆。我有频道、消息和用户。 一旦我的聊天组件加载,频道就会使用来自 Apollo 的 useQuery 钩子获取。

默认情况下,当用户访问聊天组件时,他需要单击特定频道才能查看有关频道的信息以及消息。

在较小的 Channel.js 组件中,我将点击的 Channel 的 channelid 写入 apollo-cache。这很完美,我在 Messages.js 组件中使用 useQuery 钩子 @client 从缓存中获取 channelid 并且它运行完美。

当我使用useLazyQuery 挂钩获取特定频道(用户点击的频道)的消息时,问题就出现了。

它会在 React 中导致无限的重新渲染循环,从而导致应用程序崩溃。

我已经尝试使用带有跳过选项的普通useQuery 钩子。然后我在需要时调用refetch() 函数。从它没有给我无限循环的意义上说,这“有效”。 但随后console.log() 给了我这个错误:[GraphQL error]: Message: Variable "$channelid" of required type "String!" was not provided. Path: undefined。这很奇怪,因为我的架构和变量是正确的??

如前所述,useLazyQuery 确实给了我无限循环。

我真的在为 apollo/react hooks 的条件而苦苦挣扎……

/// Channel.js 组件 ///


const Channel = ({ id, channelName, channelDescription, authorName }) => {
  const chatContext = useContext(ChatContext);

  const client = useApolloClient();
  const { fetchChannelInfo, setCurrentChannel } = chatContext;

  const selectChannel = (e, id) => {
    fetchChannelInfo(true);
    const currentChannel = {
      channelid: id,
      channelName,
      channelDescription,
      authorName
    };
    setCurrentChannel(currentChannel);

    client.writeData({
      data: {
        channelid: id
      }
    });
    // console.log(currentChannel);
  };

  return (
    <ChannelNameAndLogo onClick={e => selectChannel(e, id)}>
      <ChannelLogo className='fab fa-slack-hash' />
      <ChannelName>{channelName}</ChannelName>
    </ChannelNameAndLogo>
  );
};

export default Channel;

/// Messages.js 组件 ///


const FETCH_CHANNELID = gql`
  {
    channelid @client
  }
`;


const Messages = () => {
  const [messageContent, setMessageContent] = useState('');
  const chatContext = useContext(ChatContext);
  const { currentChannel } = chatContext;
  // const { data, loading, refetch } = useQuery(FETCH_MESSAGES, {
  //   skip: true
  // });

  const { data: channelidData, loading: channelidLoading } = useQuery(
    FETCH_CHANNELID
  );

  const [fetchMessages, { data, called, loading, error }] = useLazyQuery(
    FETCH_MESSAGES
  );

  //// useMutation is working
  const [
    createMessage,
    { data: MessageData, loading: MessageLoading }
  ] = useMutation(CREATE_MESSAGE);

  if (channelidLoading && !channelidData) {
    console.log('loading');
    setInterval(() => {
      console.log('loading ...');
    }, 1000);
  } else if (!channelidLoading && channelidData) {
    console.log('not loading anymore...');
    console.log(channelidData.channelid);
    fetchMessages({ variables: { channelid: channelidData.channelid } });
    console.log(data);
  }

我希望在来自 useLazyQuery 的数据中包含消息......但是在 console.log() 中得到这个:

react-dom.development.js:16408 Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop.

【问题讨论】:

    标签: reactjs apollo react-apollo apollo-client


    【解决方案1】:

    您在每次渲染时调用fetchMessages。 尝试将fetchMessages 放在useEffect 中:

    useEffect(() => {
        if (!channelidLoading && channelidData) {
            fetchMessages();
        }
    
    }, [channelidLoading, channelidData]);
    

    就像fetchMessages 函数仅在以下情况下调用 channelidLoading 或 channelidData 正在改变。

    【讨论】:

      【解决方案2】:

      您可以使用called 变量返回useLazyQuery

      !called &amp;&amp; fetchMessages({ variables: { channelid: channelidData.channelid } });

      【讨论】:

        【解决方案3】:

        您还可以考虑执行以下操作:

           import debounce from 'lodash.debounce';
           ...
        
           const [fetchMessages, { data, called, loading, error }] = useLazyQuery(
            FETCH_MESSAGES
          );
          const findMessageButChill = debounce(fetchMessages, 350);
          ...
          } else if (!channelidLoading && channelidData) {
            findMessageButChill({
               variables: { channelid: channelidData.channelid },
            });
          }
        
        
        

        【讨论】:

          猜你喜欢
          • 2020-01-25
          • 2021-01-29
          • 2020-06-13
          • 2020-05-18
          • 1970-01-01
          • 2021-09-26
          • 2020-02-23
          • 2018-02-10
          • 2019-10-05
          相关资源
          最近更新 更多