简体   繁体   English

具有动态路径和动态组件的 React Router

[英]React Router with dynamic path and dynamic component

I'm building the app with hierarchical structure and ability to set any slug url the user wants by the admin panel.我正在构建具有分层结构的应用程序,并且能够通过管理面板设置用户想要的任何 slug url。 For example, if the top page has url news and the page inside has url new_telescope , the whole url would be /news/new_telescope/ .例如,如果首页有 url news而里面的页面有 url new_telescope ,那么整个 url 就是/news/new_telescope/ I wrote the url controller to handle this, so it really doesn't matter how many levels are there in the url - I get the data of the needed page from the server.我编写了 url 控制器来处理这个问题,所以 url 中有多少级别并不重要 - 我从服务器获取所需页面的数据。 So my React Router wouldn't have predefined urls - I need to take the current url, send it to server, get the data, get the component and render it.所以我的React Router不会有预定义的 url——我需要获取当前的 url,将其发送到服务器,获取数据,获取组件并渲染它。 Now it looks like this:现在看起来像这样:

function getRoute() {
    url.splice(0, 1);
    adminRequest(
        'get',
        constants.SERVER_ADDRESS + `/system/url/?url=` + JSON.stringify(url) + '&version=1',
    ).then(response => {
        const CurrentComponent = lazy(() => import('./' + response.data.template));
        return <Route path={window.location.pathname} element={<CurrentComponent page={response.data}/> } />
    });
}

return (
    <>
        <Suspense fallback={<div className='preloader'><CircularProgress size='75px' /></div>}>
            <Routes>
                // trying to get the current url with proper component
                { getRoute() }
                <Route path="/admin/" element={<Admin />} />
                <Route path="/admin/login/" element={<Login />} />
                ...
            </Routes>
        </Suspense>
    </>
);

So the problem is with the getRoute function.所以问题出在getRoute函数上。 As you can see I make a request, get the component name from the DB and use lazy to import it.如您所见,我提出了一个请求,从数据库中获取组件名称并使用lazy导入它。 In that function I make a new Route to put it to Routes .在该函数中,我创建了一个新Route以将其放入Routes But I get errors No routes matched location with any url.但我收到错误No routes matched location And of course the component doesn't render.当然,组件不会渲染。 I thought that Suspense will wait for the first route to appear but it doesn't work that way.我认为Suspense会等待第一条路线出现,但它不会那样工作。 How can I make a Router to wait for a dynamic route?如何让Router等待动态路由?

Issue问题

  1. The getRoute function doesn't return anything. getRoute函数不返回任何内容。 Sure, the Promise chain started from adminRequest returns some JSX, but that resolved value isn't returned by the other function.当然,从adminRequest开始的 Promise 链会返回一些 JSX,但其他函数不会返回解析后的值。
  2. React render functions are 100% synchronous functions. React 渲染函数是 100% 同步函数。 You can't call an asynchronous function and expect React to wait for any asynchronous code to resolve to render any content.您不能调用异步函数并期望 React 等待任何异步代码解析以呈现任何内容。

Solution解决方案

Use a useEffect hook to issue the side-effect of fetching the route.使用useEffect挂钩发出获取路由的副作用。 Unconditionally render the Route but conditionally render the element value.无条件渲染Route但有条件地渲染element值。

const [data, setData] = useState();
const [CurrentComponent, setCurrentComponent] = useState();

useEffect(() => {
  const getRoute = async () => {
    url.splice(0, 1);
    const response = await adminRequest(
      "get",
      constants.SERVER_ADDRESS +
        `/system/url/?url=` +
        JSON.stringify(url) +
        "&version=1"
    );
    
    const CurrentComponent = lazy(() =>
      import("./" + response.data.template)
    );
    
    setData(response.data);
    setCurrentComponent(CurrentComponent);
  };

  getRoute();
}, [url]);

...

<Suspense fallback={<div className="preloader">Loading...</div>}>
  <Routes>
    <Route
      path={/* whatever the path is */}
      element={CurrentComponent ? <CurrentComponent page={data} /> : null}
    />
    <Route path="/admin/" element={<Admin />} />
    <Route path="/admin/login/" element={<Login />} />
  </Routes>
</Suspense>

Demo演示

编辑 react-router-with-dynamic-path-and-dynamic-component

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM