在 aws amplify subscriptions react 中访问状态的最新值

Access latest value of state in aws amplify subscriptions react

我有一个使用 aws-amplify 的订阅监听器的 useEffect 挂钩。

useEffect(() => {
        todoUpdatedSubs.subscribe({
          next: (status: SubscriptionStatus<OnTodoUpdatedSubscription>) => {
            setIsTaskUpdated(true);
            // when mutation will run the next will trigger
            console.log("New Updated SUBSCRIPTION ==> ", status);
            if (!status.value.data.onTodoUpdated.success)
              return console.log("error", status);
    
            const newArr = [...todos];
            console.log("Prev todos", todos);
            const { id, todo, isCompleted } = status.value.data.onTodoUpdated;
            newArr[editingIndex] = { id, todo, isCompleted };
            setTodos(newArr);
          },
        });}, [])

问题是 useEffect 中的下一个函数没有 todo 状态的最新值,因为 useEffect 仅 运行 挂载。如果我这样做,就会安装多个侦听器:

useEffect(() => {
        todoUpdatedSubs.subscribe({
          next: (status: SubscriptionStatus<OnTodoUpdatedSubscription>) => {
            setIsTaskUpdated(true);
            // when mutation will run the next will trigger
            console.log("New Updated SUBSCRIPTION ==> ", status);
            if (!status.value.data.onTodoUpdated.success)
              return console.log("error", status);
    
            const newArr = [...todos];
            console.log("Prev todos", todos);
            const { id, todo, isCompleted } = status.value.data.onTodoUpdated;
            newArr[editingIndex] = { id, todo, isCompleted };
            setTodos(newArr);
          },
        });}, [todos])

如何获取监听器中状态的最新值?

使用 useState 挂钩的 functional updates 选项。使用回调设置状态时,将使用先前的值调用回调。这使您无需将 todos 定义为 useEffect.

的依赖项
useEffect(() => {
  todoUpdatedSubs.subscribe({
    next: (status: SubscriptionStatus<OnTodoUpdatedSubscription>) => {
      setIsTaskUpdated(true);
      // when mutation will run the next will trigger
      console.log("New Updated SUBSCRIPTION ==> ", status);
      if (!status.value.data.onTodoUpdated.success)
        return console.log("error", status);
        
      setTodos(todos => {
        const newArr = [...todos];
        const { id, todo, isCompleted } = status.value.data.onTodoUpdated;
        newArr[editingIndex] = { id, todo, isCompleted };
        
        return newArr;
      });
    },
});}, [])

如果您需要在useEffect中使用更新后的todos值,但在更新状态时不需要,您可以使用useRef代替。

在你的情况下,我会使用功能更新选项,但我添加这个作为示例:

const todosRef = useRef();

useEffect(() => {
  todosRef.current = todos;
});

useEffect(() => {
  todoUpdatedSubs.subscribe({
    next: (status: SubscriptionStatus<OnTodoUpdatedSubscription>) => {
      setIsTaskUpdated(true);
      // when mutation will run the next will trigger
      console.log("New Updated SUBSCRIPTION ==> ", status);
      if (!status.value.data.onTodoUpdated.success)
        return console.log("error", status);
        
      const newArr = [...todosRef.current];
      const { id, todo, isCompleted } = status.value.data.onTodoUpdated;
      newArr[editingIndex] = { id, todo, isCompleted };
      setTodos(newArr);
    },
});}, [])