I stared to experiment with https://github.com/gbj/leptos/ using the current main branch from Git. Following the router example I get the following warning in my console in the browser:
WARNING: You are providing a context of a type
(leptos_reactive::memo::Memo<leptos_router::components::routes::RouterState>)that's
already been provided higher in the context tree. If this is
unintentional, there's a chance it will cause bugs, because the value
of the context is now 'shadowed' in the lower parts of the tree.
I understand the message, but I have no idea what I'm doing wrong. My router component looks like this:
#[component]
pub fn Playground(
cx: Scope,
) -> impl IntoView {
view! { cx,
<Router>
<nav>
<A exact=true href="/">"Simple"</A>
"Demo 1"
"Demo 2"
</nav>
<main>
<Routes>
<Route
path="/"
view=move |cx| view! { cx, <SimpleComponent/> } />
<Route
path="demo1"
view=move |cx| view! { cx, <Demo1 /> } />
<Route
path="demo2"
view=move |cx| view! { cx, <Demo2 /> } />
</Routes>
</main>
</Router>
}
}
If I recall correctly you found your way to our Discord. Basically this is an over-zealous warning I added a couple days ago in our main branch but probably need to revert.
In general I’d probably discourage asking questions that are so specific to particular libraries on Stack Overflow, especially when it’s a smallish and new library.
Related
I'm creating a sign in screen and a create account screen on my application. I have buttons that go back and forth to each other. Both screens work fine individually. When I do this, there can often be a visual error like so:
My App.js Code:
const App = () => {
return (
<NavigationContainer theme={theme}>
<Stack.Navigator screenOptions={{ headerShown: false}} initialRouteName="CreateAccountScreen">
<Stack.Screen name ="CreateAccountScreen" component={CreateAccountScreen} />
<Stack.Screen name ="SignInScreen" component={ SignInScreen } />
</Stack.Navigator>
</NavigationContainer>
);
}
Code from each Screens button that goes back and forth:
onSignUpButtonPressed = () => {
navigation.navigate("SignInScreen")
}
onCreateAccountButtonPressed = () => {
navigation.navigate("CreateAccountScreen")
}
Displays seem to overlay themselves in a bad way
I've tried a bunch of things and this has happened on several screens...
Your initialRouteName is set up as we can see but on your Stack.Screen you also give it the Component attribute.
I did a test based on how my navigation looks and I did not get the visual bug you showed so I think if you removed the component attribute and maybe just put the component tag inside your Stack.Screen as shown below it might work. Just imagine my Home is your CreateAccountScreen.
<Stack.Navigator
initialRouteName='Home'
>
<Stack.Screen
name="Home"
options={{
headerShown: false,
}}
>
{props => <Home {...props} username='Bella' />}
</Stack.Screen>
You also dont have the code in your question to define Stack like this:
const Stack = createStackNavigator();
We're using react 16.13 and react-router-dom 5.1.2 but we struggle to make it work the way we want:
it works great when used with our https://react.domain.com/
but it doesn't when a user starts the app directly on a subpage, https://react.domain.com/page1 as we can't find any way to tell react-router that the base url is still / and not page1/
(We've configured the nodejs/express backend to send the react app no matter the route)
So react-router just adds all the history / path to the /page1 url, resulting in /page1/login, /page1/page1, etc. instead of the /login or /page1 urls.
Is there any way to achieve that?
The goal is to allow the refresh of the page, and to allow direct access to a specific route.
EDIT: code example
client side
<StoreProvider store={store}>
<Suspense fallback={<MainPageFallback />}>
<ThemeProvider theme={theme}>
<Router basename={location.pathname}>
<I18nextProvider i18n={i18next}>
<TryCatch>
<Navbar actions={<UserSettings />} />
<div className={classes.appContent}>
<Switch>
<Route exact path="/start">
<LandingPage />
</Route>
<Route exact path="/search">
<SearchPlacePage />
</Route>
<Route exact path="/signup">
<SignUpPage />
</Route>
<Route exact path="/signin">
<LoginPage />
</Route>
<Route exact path="/forgot_password" component={ForgotPassword} />
<Redirect from="/*" to="/start" />
</Switch>
<Snackbar />
</div>
</TryCatch>
</I18nextProvider>
</Router>
</ThemeProvider>
</Suspense>
</StoreProvider>
server side
#Route('/*')
public async home({ query }: Request, res: Response) {
const { resolve } = await import('path');
const { readFileAsync } = await import('../Infrastructure/readFileAsync');
try {
const file = (await readFileAsync(resolve(__dirname, '..', '..', '..', 'static', 'index.html')))
.toString('utf-8');
return res.send(file);
} catch (err) {
return res.sendFile(resolve(__dirname, '..', '..', '..', 'static', 'notFound.html'));
}
}
You need to use Routes rather than Switch for react-router-dom#6. Something like this:
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
</Route>
</Routes>
</BrowserRouter>
I am having trouble writing code to render a login page with no navbar and sidebar. I have come across some pages that ask similar questions but none seem to pertain to my current situation.
How to hide navbar in login page in react router
the example given is great but I believe the way of accomplishing that same task has changed with react-router-dom v6 leading me to read about this change in https://dev.to/iamandrewluca/private-route-in-react-router-v6-lg5
It seems I am not understanding a certain aspect about routing with React Router. In the code below I have two Routes. One of the routes(Login) I would like to have render without the NavBar and SideBar component.
const App = () => {
return (
<>
<Routes>
<Route path="/login" element={<LoginPage />} />
</Routes>
<NavBar />
<SideBar />
<main className={styles["main--container"]}>
<div className={styles["main--content"]}>
<Routes>
<Route path="/" element={<Dashboard />} />
</Routes>
</div>
</main>
</>
);
};
An alternative, that I also tried, would be to move the NavBar and SideBar tags into the Dashboard component, but then I would essentially have to do the same copy and paste for any new components. This method felt wrong and inefficient , but if this is the correct way of doing it I will do the needful
Edit: I think it's important to include what it currently does is load the Login page with the NavBar and SideBar included. Navigating to the dashboard component has the NavBar and SideBar but this is intended.
What I would like is for the Login page not to have the NavBar and SideBar
If I understand your question, you are wanting to render the nav and sidebar on the non-login route. For this you can create a layout component that renders them and an outlet for the nested routes.
Using nested routes
import { Outlet } from 'react-router-dom';
const AppLayout = () => (
<>
<NavBar />
<SideBar />
<main className={styles["main--container"]}>
<div className={styles["main--content"]}>
<Outlet /> // <-- nested routes rendered here
</div>
</main>
</>
);
const App = () => {
return (
<>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route element={<AppLayout />} >
<Route path="/" element={<Dashboard />} /> // <-- nested routes
</Route>
</Routes>
</>
);
};
Using a routes configuration and useRoutes hook
const routesConfig = [
{
path: "/login",
element: <LoginPage />,
},
{
element: <AppLayout />,
children: [
{
path: "/",
element: <Dashboard />,
},
],
},
];
...
import { useRoutes } from 'react-router-dom';
const App = () => {
const routes = useRoutes(routesConfig);
return routes;
};
Using a routes configuration and data routers (introduced in v6.4.0)
const routesConfig = [
{
path: "/login",
element: <LoginPage />,
},
{
element: <AppLayout />,
children: [
{
path: "/",
element: <Dashboard />,
},
],
},
];
...
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter(routesConfig);
const App = () => {
return <RouterProvider router={router} />;
};
The easiest way for you to hide the navbar would be to go to the login page component and call useLocation(). Then you woulf do something like this after declaring the use location. And assigning it to a variable location
{ location.pathname === "/login" ? null : (
Render the whole navbar component);
Not sute if you can be able to read as I type from my phone
I am using Qiankun as a micro-frontend-servlet and need someone, who has a bit of knowledge around that tool, who can help me with the following problem:
My Master-Application, as well as all Micro-Applications run on a react-app, which have been created via "npx create-react-app".
It seems to me, that the routes defined in the -Component seem to work once. To be specific:
If i click on one -Component redirecting the browser to "/react-app" , this works just fine. If i then, and that is the crucial part of that whole problem, click on the other link, to the other micro-application. The whole page goes blank and in the web-console you'll find the following error:
Uncaught Error: application 'react app1' died in status LOADING_SOURCE_CODE: [qiankun]: Target container with #react-app1 not existed while react app1 loading!
There's an FAQ-section on the site just covering this issue, but i can't wrap my head around that on how it is done the proper way.
Qiankun-FAQ's
Master-Application:
(...)
function App(props) {
registerMicroApps([
{
name: "react app", // app name registered
entry: "//localhost:3001",
container: "#react-app",
activeRule: "/react-app",
},
{
name: "react app1", // app name registered
entry: "//localhost:3002",
container: "#react-app1",
activeRule: "/react-app1",
},
]);
start()
return (
<div className="App">
{/* <div id="react-app"></div> */}
<Header></Header>
<Router>
<Switch>
<Route exact path="/"></Route>
<Route exact path="/react-app">
<div id="react-app"></div>
</Route>
<Route exact path="/react-app1">
<div id="react-app1"></div>
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
(...)
Header-Component, having the Main-Routes configured:
const Header = (props) => {
return (
<div className={Styles.Header}>
<img alt="Avocodo Logo" src={Logo}></img>
<h1>Main Application</h1>
<BrowserRouter /*basename={window.__POWERED_BY_QIANKUN__ ? '/react-app' : '/'}*/>
<Link to="/react-app">Sub-App</Link>
<Link to="/react-app1">Sub-App1</Link>
</BrowserRouter>
</div>
);
};
export default Header;
One of the two identical Micro-Applications:
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import './App.css';
function App() {
return (
<div className="App">
<BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react-app1' : '/'}>
<h2>Sub-App2</h2>
</BrowserRouter>
</div>
);
}
export default App;
Has anyone ever worked w/Qiankun and can help me on how to get the issue solved?
Thankful for any hints!
<Route exact path="/"></Route>
<Route exact path="/react-app">
<div id="react-app"></div>
</Route>
<Route exact path="/react-app1">
<div id="react-app1"></div>
</Route>
the divs with IDs "react-app" and "react-app1" should be kept outside the switch tag. They need to be available when the micro-app is being registered.
But in your case, the div is available only if the route is selected. So before you navigate another route, qiankun tries to register the micro-app to the dom element, which has not been added yet.
I am having a hard time setting up my react-router so that when the path matches the user's username, the userProfile component will be routed and show individually. For example, when the URL is http://localhost:3000/myusername, the userProfile component will only show. I'm kind of confused on how it will work if someone just pastes the entire link instead of being directed to someone's page through the UI.
<Switch>
<Route path="/" component={userProfile} />
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/test3" component={test3} />
</Switch>
Any help would be appreciated!
You can use this method and access to username in test3 component and handle getting data and showing this page
<Switch>
<Route path="/" component={userProfile} />
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/:username" component={test3} />
</Switch>
I found that if you just use /:id in the path, then the path extension will pass automatically down to the userProfile component when you use the const {id} = useParams() function in the userProfile component. Then I passed the _id down as a prop from the userProfile component to the Info component so that it can be used to automatically fetch data in a useEffect() and redux dispatch() function. Oh and also, the <Route path="/:id" component={userProfile} /> needs to be an exact path and must go to the bottom of the Route Switch list so that it doesn't get picked first.
<Switch>
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/test3" component={test3} />
<Route exact path="/:id" component={userProfile} />
</Switch>
const Profile = () => {
const { id } = useParams();
return (
<div>
<Info _id={id} />
</div>
);
};
export default Profile;
const Info = (props) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getProfileInfo(props._id));
}, []);
return (
<div></div>
);
};
export default Info;