我正在建立一个不和谐/松弛的克隆。我有频道,消息和用户。
当我的聊天组件加载后,便会通过Apollo的useQuery
钩子获取频道。
默认情况下,当用户来到“聊天”组件时,他需要单击特定的频道以查看有关该频道的信息以及消息。
在较小的Channel.js组件中,我将单击的Channel的channelid写入了阿波罗缓存。效果很好,我在Messages.js组件中使用了useQuery
钩@client来从缓存中获取通道ID,并且效果很好。
当我使用useLazyQuery
挂钩来获取特定频道(用户单击的频道)的消息时,就会出现问题。
它会在React中导致无限的重新渲染循环,从而导致应用崩溃。
我尝试使用带有skip选项的普通useQuery
挂钩。然后在需要时调用refetch()
函数。从某种意义上说,这种“运作”没有给我无限循环。
但是随后console.log()
给了我这个错误:[GraphQL error]: Message: Variable "$channelid" of required type "String!" was not provided. Path: undefined
。这很奇怪,因为我的架构和变量是正确的??
useLazyQuery确实给了我无限循环,如前所述。
我真的在为阿波罗/反应钩的条件而苦苦挣扎...
/// 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.
答案 0 :(得分:2)
您在每个渲染器上调用fetchMessages
。
尝试将fetchMessages
放在useEffect
中:
useEffect(() => {
if (!channelidLoading && channelidData) {
fetchMessages();
}
}, [channelidLoading, channelidData]);
就像fetchMessages
函数仅在
channelidLoading或channelidData正在更改。
答案 1 :(得分:2)
您可以使用called
返回的useLazyQuery
变量。
!called && fetchMessages({ variables: { channelid: channelidData.channelid } });
答案 2 :(得分:0)
您还可以考虑执行以下操作:
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 },
});
}