React Hooks 在设置状态的同时处理多个动作的方式是啥?

Posted

技术标签:

【中文标题】React Hooks 在设置状态的同时处理多个动作的方式是啥?【英文标题】:What is the React Hooks way of handling multiple actions while also setting state?React Hooks 在设置状态的同时处理多个动作的方式是什么? 【发布时间】:2021-08-03 10:40:05 【问题描述】:

我有 4 个组件:App, CatalogList, CatalogPreview, CatalogDetail

App 是父组件,我有这些状态值:

const [catalog, setCatalog] = useState( id: 1, name: 'Electronics' )
const [isModalOpen, setIsModalOpen] = useState(false)

CatalogListCatalogPreview 组件接收上述状态值作为 props 以及它们的 setter 函数。

内部CatalogList.js

我有一个目录链接列表(电子产品、家具……),当您单击其中一个链接时, 它打开了CatalogPreview 模式。在模态框内,有一个 'Explore' 按钮。

当你点击'探索'按钮时,它需要做4件事:

将所选目录设置为状态(在 App.js 中) 将所选目录保存在 localStorage 导航到详细信息页面 关闭模态窗口

我在 'Explore' 按钮的点击处理程序(在模式内)中尝试了以下操作:

function explore() 
  props.setCatalog(...)
  props.setIsModalOpen(false)
  window.localStorage.setItem('catalog', JSON.stringify(...)
  history.push('detail-route') // this brings up the CatalogDetail

Link to Code Sandbox

问题:

    这是正确的方法吗? 在CatalogDetail 组件中,如果我单击“删除”按钮并发出删除 API 请求,如何在调用完成之后导航回CatalogList 路由。

【问题讨论】:

这不一定是不正确的,尽管恕我直言,它可以改进。如果您可以更新您的问题以包含每个组件的完整 Minimal, Complete, and Reproducible Code Example,我想我可以更好地提出建议。 @DrewReese 添加了代码沙箱链接 【参考方案1】:

    与其将模态打开/关闭状态存储在父 App 组件中,不如将其降级为管理模态的子 CatalogList 组件。

    将持久化到 localStorage 移动到依赖于 catalog 状态的 useEffect 挂钩。当状态更新时,将其持久化到 localStorage。

    创建一个updateCatalog 回调函数以接受一个新值来更新目录状态。将此传递给CatalogList

    explore 回调应该提升/提升到CatalogList 组件。这允许CatalogPreview 基本上只渲染模态。 explore 仍然调用更新目录数据、关闭模式和导航。

    应用程序

    function App() 
      const [catalog, setCatalog] = useState( id: 1, name: "Electronics" );
    
      useEffect(() => 
        window.localStorage.setItem("catalog", JSON.stringify(catalog));
      , [catalog]);
    
      const updateCatalog = value => 
        setCatalog( ...value... );
      ;
    
      return (
        <Switch>
          <Route exact path="/">
            <CatalogList updateCatalog=updateCatalog />
          </Route>
          <Route exact path="/detail">
            <CatalogDetail catalog=catalog />
          </Route>
        </Switch>
      );
    
    

    目录列表

    function CatalogList(props) 
      const history = useHistory();
    
      const [isOpen, setIsOpen] = useState(false);
      const catalogs = [
         id: 1, name: "Electronics" ,
         id: 2, name: "Furniture & Appliances" ,
         id: 3, name: "Sports & Outdoors" 
      ];
    
      const openPreview = () => 
        setIsOpen(true);
      ;
    
      function explore() 
        props.updateCatalog(... some new value ...);
        setIsOpen(false);
        history.push("/detail");
      
    
      return (
        <div>
          Available catalogs
          <ul>
            catalogs.map((c, index) => (
              <li key=c.id onClick=() => openPreview(c.id) className="link">
                c.name
              </li>
            ))
          </ul>
          <CatalogPreview isOpen=isOpen onExplore=explore />
        </div>
      );
    
    

    目录预览

    function CatalogPreview(props) 
      return (
        <Modal show=props.isOpen>
          <Modal.Header closeButton>
            <Modal.Title>Catalog Preview</Modal.Title>
          </Modal.Header>
          <Modal.Footer>
            <Button variant="primary" onClick=props.onExplore>
              Explore
            </Button>
          </Modal.Footer>
        </Modal>
      );
    
    

    使用useHistory 并更新onClick 处理程序以导航回主页。

    function CatalogDetail(props) 
      const history = useHistory();
    
      return (
        <div>
          <p>Detail Page</p>
          <button
            onClick=() => 
              // Make API call then navigate home
              history.push("/");
            
          >
            DELETE
          </button>
        </div>
      );
    
    

演示

【讨论】:

以上是关于React Hooks 在设置状态的同时处理多个动作的方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

React:使用 Hooks 为深度嵌套对象设置状态

在状态对象中使用具有多个键/值对的 React Hooks

React Hooks - 等待多个状态更新完成

React Hooks - 将状态设置为初始状态

react hooks的缺点(针对状态不同步和没有生命周期)

react hooks的缺点(针对状态不同步和没有生命周期)