Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 阿波罗突变与种族条件_Reactjs_Graphql_Apollo_React Apollo - Fatal编程技术网

Reactjs 阿波罗突变与种族条件

Reactjs 阿波罗突变与种族条件,reactjs,graphql,apollo,react-apollo,Reactjs,Graphql,Apollo,React Apollo,(这是一项后续行动) 我正在尝试构建一个文本输入,它将随着用户的输入而更新值 第一次尝试 我首先尝试使用optimisticResponse在用户输入时更新本地缓存。这是有效的,除了它在每一个按键上都会触发一个突变。除了请求充斥网络之外,还存在网络不一致的问题。可能是最后一个突变最先到达,而第一个突变最后到达。这将导致服务器以过时的值结束。以下是此竞赛条件的示例: type: a mutate request: a type: b mutate request: ab arrives on se

(这是一项后续行动)

我正在尝试构建一个文本输入,它将随着用户的输入而更新值

第一次尝试 我首先尝试使用
optimisticResponse
在用户输入时更新本地缓存。这是有效的,除了它在每一个按键上都会触发一个突变。除了请求充斥网络之外,还存在网络不一致的问题。可能是最后一个突变最先到达,而第一个突变最后到达。这将导致服务器以过时的值结束。以下是此竞赛条件的示例:

type: a
mutate request: a
type: b
mutate request: ab
arrives on server: ab
arrives on server: a
现在服务器在graphql中记录了“a”,这是不正确的

添加去盎司 为了缓解这种情况,我在keypress事件中添加了一个去抖动。虽然这确实有助于上述比赛条件,但它并不能解决问题。如果网络速度低于你的去盎司阈值,仍然有可能出现竞争状况

因为我们现在正在对文本输入进行去Bouncing,所以需要为React组件引入一个本地状态,以便它在用户键入时立即更新(正如github问题中@jbaxleyiii所建议的)。现在我们的状态位于两个位置(组件状态和apollo缓存)

这样做的一个大问题是组件在收到新道具时不会更新。例如,当graphql得到更新并推送到客户端时

添加网络队列 因为debounce实际上并没有解决竞争条件,所以我添加了一个网络队列(除了debounce之外),该队列将管理变异请求,以确保一次只有一个变异。如果它在飞行中收到一个变异请求,它将排队等待第一个变异请求返回时被触发。如果已经有一个变异排队,它将丢弃它并用新的替换它(一次队列中只能有一个项目)。下面是一个例子:

type: a
send mutate request: a
type: b
queues mutate request: ab     <<  wait to send this until "a" comes back
type: c
replaces queued request: abc  << discard the queued request for "ab", it's old now
response from server: a
send mutate request: abc      << send the queued mutation and clear the queue
response from server: abc
action                   | cache
-------------------------+------------
type: a                  | a
mutate request: a        | a
type: b                  | ab
queues request: ab       | ab
response from server: a  | a  << oh no!
mutate request: ab       | a  << we're not using optimisticResponse anymore
... network time ...     | a
response from server: ab | ab
我想我们可以使用
client.writeQuery
在用户键入时更新缓存,并使用
optimisticResponse
在触发变异请求时更新缓存,但现在这段代码变得很难理解了

update
函数中也可能有一种方法来处理这个问题,但我还没有做到这一点

帮忙?
我是阿波罗的新手,所以我可能错过了什么。有没有更好的方法来处理阿波罗中的许多快速突变?

每一个突变都会带来一个希望,这样你就可以通过跟踪最新的突变来知道什么时候发生了无序突变

因为您接受用户输入的任何内容,这意味着用户的值是规范值,您并不真正需要乐观的响应。您要做的就是确保服务器的值与您的值相同

因此,我建议您跟踪Redux中的输入,并添加一个触发突变(使用debounce)的存储侦听器


如果您确实需要跟踪服务器值,请使用计数器查看返回的突变是否是最后一个(在突变发送时存储++计数器值,并将该值与突变返回时的计数器值进行比较)。

在2020年发现此线程。我试图用
adddebounce
方法解决这个问题,到目前为止效果相当不错

如原问题所述,主要的挑战是保持组件状态与apollo缓存同步。我引入了一个useEffect来更新道具更改时的本地缓存。下面的代码段是我创建的帮助程序挂钩,用于编辑需要与服务器同步的任务。请注意,必须使用
optimisticResponse
调用突变。触发变异后,apollo缓存将返回一个新的任务对象。它将替换本地cachedTask。稍后,当服务器响应返回时,apollo足够聪明,能够发现它与乐观响应是同一个对象,因此本地缓存不会再次更新。如果您在网络事务的中间进行更改,则由于该机制,您的更改不会被重写。
导出函数useNewConnectedTask(defaultTask){
const[cachedTask,setCachedTask]=useState(defaultTask);
const[updateTask]=useUpdateTask();
useffect(()=>{
setCachedTask(defaultTask);
},[defaultTask]);
const debouncedUpdateTask=useCallback(
去盎司((任务)=>{
更新任务({
变量:{
数据:任务,
},
乐观回应:{
__typename:'突变',
更新任务:,
},
});
},1000),[updateTask],
);
const setTask=useCallback(
(任务:TaskFieldsDetailedFragment)=>{
setCachedTask(任务);
去BouncedUpdateTask(任务);
},[setCachedTask,debouncedUpdateTask],
);
返回[cachedTask,setTask];
}