React.js:如何在首次渲染之前先调用钩子?

时间:2020-05-05 08:49:44

标签: reactjs

我正在尝试使用React创建一个动态菜单

我有一个JSON响应,其中包含菜单的外观:

[
      { id: 0,
        label: "Dashboard",
        link: "/app/dashboard",
        icon: <HomeIcon /> },
      {
        id: 1,
        label: "Inward",
        link: "/app/inward",
        icon: <InboxIcon />,
        children: [
          { label: "PESONet", link: "/app/inward/pesonet" },
          { label: "PESONet Inquiry", link: "/app/inward/pesonetinquiry" },
          { label: "PDDTS", link: "/app/inward/pddts" },
          { label: "SWIFT", link: "/app/inward/swift" },
          { label: "Philpass", link: "/app/inward/philpass" },
        ],
      }
]

我可以通过以下方式将此JSON响应置于状态:

Sidebar.js

const [sideBar, setSideBar] = useState([])

useEffect(() => {
    const sidebar = customizeSidebar()
    setSideBar(sidebar)
  }, [])

可以在我的上下文中找到函数customizeSidebar()

UserContext.js

function customizeSidebar(dispatch, profileId, history){
  ProfileMaintenanceService.retrieveSideMenu()
  .then((response) => {
    return response.data
  }).catch((err) => {
    // check first if api is down
  })
}

如您所见,每当收到回复时,我也会将其返回。

因此,我可以在Sidebar.js中获得它。

但是,当在useEffect函数之前首先进行渲染时会出现问题。

const [sideBar, setSideBar] = useState([])

  useEffect(() => {
    const sidebar = customizeSidebar()
    setSideBar(sidebar)
  }, [])

return (
 <List className={classes.sidebarList}>
        {sideBar.map(link => (
          <SidebarLink
            key={link.id}
            location={location}
            isSidebarOpened={isSidebarOpened}
            {...link}
          />
        ))}
      </List>
)

已经尝试使用useLayoutEffect,但是渲染仍然首先发生在我的API调用和分配给状态之前。

有什么方法可以执行我的API调用并在第一次渲染之前分配给state?

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

最好的imo是做这样的事情

return (
 {sideBar.length&&<List className={classes.sidebarList}>
        {sideBar.map(link => (
          <SidebarLink
            key={link.id}
            location={location}
            isSidebarOpened={isSidebarOpened}
            {...link}
          />
        ))}
      </List>}
)

因此,仅在侧边栏数据数组已满时才会显示侧边栏。

答案 1 :(得分:0)

要么返回一个占位符,要么没有侧边栏数据:

if (!sideBar.length) {
  return (
    <div className="sidebar-placeholder">
      <Spinner/> || Loading text...
    </div>
  );
}

return (
  <List>...
);

或者您将补充工具栏包装在提供程序组件中,并通过补充工具栏配置作为道具。