【问题标题】:What is the best way to update my react state when data in database changes?当数据库中的数据发生变化时,更新我的反应状态的最佳方法是什么?
【发布时间】:2021-09-24 14:43:52
【问题描述】:

我正在使用 React 进行一个项目,当新数据插入我的数据库时,我需要使用 react 钩子更新反应状态。我正在使用 contextAPI,但就我而言,我的组件的结构方式无法使用从数据库返回的数据更新该状态。这是我的代码的更多细节:

我有一个组件,其中数据存在于 useState

const [questions, setQuestions] = useState([]);

  useEffect(() => {
    (async () => {
      const resp = await axios.get(
        `${process.env.REACT_APP_BACKEND_URL}/product/${productId}/question`
      );
      setQuestions(resp.data);
    })();
  }, []);

我还有另一个名为 PostQuestion 的组件,它将发布请求发送到我的后端并将新问题插入我的数据库。他们完全不知道彼此的存在。我们可以使用 contextAPI 将 props 传递给孩子和嵌套的孩子。但是 PostQuestion 组件不是所有问题数据都存在的那个组件的子组件。这就是我对 contextAPI 的理解。但他们都是另一个组件的孩子。但我不想放置我的

 const [questions, setQuestions] = useState([]);

在这两个组件的父组件中。我可以做些什么来更新我的 PostQuestion 组件中的问题状态?

这是我的 PostQuestion 组件代码


const postQuestionHandler = async (e) => {
    e.preventDefault();

    try {
      const resp = await axios({
        url: `${process.env.REACT_APP_BACKEND_URL}/product/${productId}/question`,
        method: "POST",
        data: {
          question: questionInput.question.value,
          userId,
        },
      });
      if (resp.status === 200) {
        setShowForm(false);
      }
    } catch (err) {
      alert(err);
    }
  };

  return <SecondaryBtn disabled={questionInput.question.error}>
              Submit Your Question
    </SecondaryBtn>

总结

我有 2 个没有父子关系的组件。当我在组件 2 中取回新数据时,我想通过调用 setState 来更新组件 1 中的状态。我不想在这两个父组件中拥有状态,因为它已经足够混乱了。

如果我使用 Redux,就不会出现这样的问题。也许在 contextAPI 中也有办法做到这一点。

【问题讨论】:

    标签: reactjs react-redux react-hooks state-management react-context


    【解决方案1】:

    多种解决方案:

    1. 您可以间隔轮询。
    2. 将状态存储在父组件中(有时它们会共享一个)并将其传递下去。
    3. 使用像redux这样的全局状态管理工具,或者react的context API。我会推荐上下文 API,因为它是内置的。

    【讨论】:

    • 我正在使用 contextAPI。但就像我提到的,据我所知 contextAPI 是如何工作的,它不能用 contextAPI 完成,因为它们不是父子关系。
    • @NyiNyiHmueAung 总是有一个共同的父母。在某些时候,它们将在 App 中呈现
    • @NyiNyiHmueAung 是组件的兄弟姐妹吗?如果你愿意,我可以举个例子:)
    • 是的,绝对有一个共享的父级。但我不想让我的状态在那个共享的父级中,因为它没有意义。我在想会有其他的方法来做到这一点。其他替代品。
    • 好吧,使用上下文,您至少可以将 Context 放在父级中。例如,如果您有多个创建、管理和删除用户的页面,您可以将提供程序放在为这些路由提供服务的路由器中。
    【解决方案2】:

    我认为 Context API 是最好的方法。

    您可以使用React.createContext 创建一个上下文,然后是一个封装您的上下文提供程序的组件。因此,PostsContextPostsProvider 将存储帖子状态并将状态和 setState 都传递给 PostsContext.Provider

    然后,为了简单起见,创建一个 usePosts 钩子,在那些需要使用上下文的子节点上,只需执行 const [posts, setPosts] = usePosts()

    好的,所以你有:

    1. 一个上下文;
    2. 您自己的 Provider 组件,将使用 Context;
    3. 使用useContext 消耗上下文的钩子;

    只是为了更清楚:

    • 上下文:
    const PostsContext = React.createContext();
    
    • 提供者:
    function PostsProvider(props) {
      const [posts, setPosts] = React.useState([]);
      
      return <PostsContext.Provider value={{ posts, setPosts }} {...props} />
    }
    
    • 一个钩子:
    function usePosts() {
      const context = React.useContext(PostsContext);
    
      function postQuestionHandler(newPost) {
        // ...
        context.setPosts((posts) => [...posts, post]);
      }
    
      return [context.posts, postQuestionHandler]
    }
    

    然后您可以使用PostsProvider 封装子组件,这些组件可以使用usePosts 挂钩访问上下文。

    这将是一个完整的场景,您可以通过其他方式划分逻辑,例如不创建自定义挂钩或自定义提供程序。在这种情况下,我个人更愿意只提升状态,但正如您所说,您的父组件已经处理了太多,也许这是一个不错的选择。

    【讨论】:

      猜你喜欢
      • 2010-09-29
      • 2022-10-24
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      相关资源
      最近更新 更多