call a component function from header componet in react router - javascript

Her is my index.js file, layout(header, middel-container, footer)
<div>
<Header />
<div className="middle-container">
<Route path="/hello" component={HelloWorldApp} />
<Route exact path="/" component={Login} />
</div>
<Footer />
</div>
I have separate file for Header, HelloWorldApp, Login and footer. On my Header component there have login button, if I click on login button it will call a function on Login component.
How I can I do that. (This is not a child, parent component so that I can pass the function name as props.)
Please help me.

Import {Link} from react-router-dom in your login component. Add a Link to "/" like **abc. If you want to call a method inside the login component(That way it should be a class component..) then You should instead try to add that state of login component in your index.js component and then you can call login stateless functional component by sending the state as props to it so you can get the desire results.
Here is an example of calling a stateless functional component:
login({[your_state_as_props]})=>
return([conclusion of your operations on props..]);
further more you can read here https://medium.com/#ruthmpardee/passing-data-between-react-components-103ad82ebd17
and if you want to pass to data between two totally separate components,(HelloWorlApp and Login) then you can... but it will totally mess up all of your program. Instead hold any data that you require to send down to child components in your topmost component or make Helloworld component a method of your main component if its a functional component or if not, try to hold it's state in your topmost component and make helloworld a method of of your first component.

Related

How to open/close a modal from my header component in Next.js 13?

I am building an e-commerce application with Next.js 13 for fun. I have difficulties when I try to make a Login modal that pops up when I click on a button in <Header/> component.
My approach would be make a useState in the parent, which is the rootLayout here, pass the setter to <Header/>, and pass the state to the modal.
But my question is, since I will be using useState to toggle the visibility of the modal, I will need to use client component by declaring "use client". But if I use "use client" in my root layout, and use the useState hook here, will it make my whole app client component? If that's the case, then this is not ideal. How should I implement it? Is it a bad layout? Should I change it? Thanks.
This is my root layout:
import "./globals.css";
import Header from "./Header";
import LoginForm from "#components/LoginForm";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head />
<body className="relative">
<Header /> <-------------------------- THIS IS THE HEADER/NAVBAR COMPONENT
<main className="p-5">
<div>{children}</div>
</main>
<LoginForm /> <------------------------ THIS IS THE LOGIN MODAL COMPONENT
</body>
</html>
);
}

React router url changes correctly but component not being rendered from button component link

I have something similar to the following CodeSandBox example where I need to use react routing within two different components.
The problem that I am facing is that, if using this codesandbox example and I click down to either the Profile or Quotes component level and assuming I have the following Material-UI button within each of these bottom components:
<Button>
text="New Item"
variant="outlined"
className={classes.newButton}
component={NewItem}
to={'/new-item'}
</Button>
When clicking on this "New Item" button, the URL changes to the correct route, i.e. /new-item but the actual NewItem component is not being rendered in the page?
If I refresh the browser, then it loads correctly.
Can anyone pls assist with the above and what the best solution is, when at this level?
Arthur, make sure in your index.js or wherever you are declaring your switch its set up like so.
<Switch>
<Route exact path="/NewItem" component={NewItem}/>
</Switch>
Then you can simply add a nav link like so
<Link to="/NewItem">New Item</Link>
the button will have a component of Link which is imported from react-router-dom
<Button>
text="New Item"
variant="outlined"
className={classes.newButton}
component={Link}
to="/new-item"
</Button>
and in the app.js you will create a Route like so :
<Switch>
<Route exact path="/NewItem" component={NewItem}/>
</Switch>
Well you shouldn't use button for changing go to new Page or going new URL. rather than use
<link to=""/> for routing but if you want to use button for going to different page than use Redirect from react-router-dom
import { Redirect } from 'react-router-dom';
const Next = (e) => {
e.preventDefault();
return <Redirect to='/NewItem' />;
};
<Button onClick={Next}>
text="New Item" variant="outlined" className={classes.newButton}
component={NewItem}
</Button>;
Or you can use Link using Link
import {Link} from 'react-router-dom';
<Link to={'/NewItem'} className={classes.newButton}>
New Item
</Link>;

How to get local state of another component using Redux

Using react + redux, I am making an app where you answer questions, 5 questions per step and about 20 steps. When starting a new step, I save the progress to localStorage.
My app structure is like this:
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div id="ocean-model">
<Topbar />
<main id="main">
<Route exact path="/" component={Landing} />
<Switch>
<PrivateRoute exact path="/survey" component={Survey} />
</Switch>
<Switch>
<AdminRoute exact path="/edit-questions" component={EditQuestions} />
<AdminRoute exact path="/add-question" component={AddQuestion} />
</Switch>
</main>
</div>
</Router>
</Provider>
);
}
}
In Survey component I use controlled inputs to save current answers to local state and on submitting all 5 answers I use redux action to save given answers to localStorage and redux store.
In Topbar component I have a button, which onClick I would like to take the current progress from redux store, but also get the currently answered questions(for example 2 out of 5), which are only available in the Survey component's local state.
Do I need to modify the App structure so that Topbar and Survey can share state or maybe in Survey I need to somehow listen to an onclick event of a button from Topbar?
Is there any reason you can't save given answer to localStorage and redux store when the input loses focus? Might need to allow for the action to fire if the Topbar component button is clicked while the focus is still on the last input with an answer.
The alternative would be to use React Context as your state container for each set of 5 questions and use that from both the form and the Topbar button with a Provider located in the component tree above both.

React Router Link dont updated page data

I have this react + redux app
I have 1 Movie component with some movie data displayed on it which are fetched from API.
So at the bottom, i decided to add a Similar movies section with a couple of components to navigate to the new movie pages.
<div className="similar_movieS_container">
{ this.props.thisMovieIdDataSIMILAR.slice(0,4).map((movie,index)=>{
return(
<Link to={"/movie/"+movie.id} key={index}>
<div className="similar_movie_container">
<div className="similar_movie_img_holder">
<img src={"http://image.tmdb.org/t/p/w185/"+movie.poster_path} className="similar_movie_img" alt=""/>
</div>
</div>
</Link>
)
})
}
</div>
Now when I'm at a root route for instance /toprated and i click on a <Link to={"/movie/"+movie.id} key={index}> i get navigated to the particular route (e.g. /movie/234525 ) and everything works fine , but if I'm in a /movies/{some move ID } route and i click on some <Link to={"/movie/"+movie.id} key={index}> The route in the URL bar gets updated, but the page stays still, meaning nothing changes if I reload the page with the new route the new movieID data is displayed...
So how can i make a navigation to a new /movie/{movieID} FOMR a /movie/{movieID} ?
It's because you are just within same route.
There are few ways to work around this. I bet you are rendering routes like this.
<Route path="/movie/:id" component={Movie} />
Try like this.
<Route path="/movie/:id" component={() => <Movie />} />
Another solution would be to use componentWillReceiveProps instead of componentWillMount.
This happens because the component of page movie was mounted, so the render method of this component will not be mounted again or updated, so you need to fire a code to change the state, and consequently re-rendering the page content, for this you can implement the componentDidUpdate method which is fired for every props modification.
https://reactjs.org/docs/react-component.html#componentdidupdate
Basically you implement the same code above inside

Navigate with javascript using the MemoryRouter in react-router

I'm building a single page web application using React. For this application, I'd like to prevent the URL from changing and also avoid using href links to prevent the "link preview" from showing up in the bottom left hand corner of browsers.
To address the first half of my problem I found that using MemoryRouter from react-router prevented URLs from changing when navigating within the application.
Here's a PoC for the router:
import App from './stuff/main/App';
import {Route, MemoryRouter} from "react-router";
import default_page from "./stuff/pages/default_page"
import another_page from "./stuff/pages/another_page"
const app = document.getElementById('root');
ReactDOM.render(
<MemoryRouter>
<App>
<Route exact path="/" component={default_page} />
<Route path="/anotherpage" component={another_page} />
</App>
</MemoryRouter>,
app
);
Then in App I have code like this (which works):
...
<Link to="/">default_page</Link>
<Link to="/anotherpage">another_page</Link>
{this.props.children}
...
I cannot figure out how to change pages in javascript using the MemoryRouter. The only method I've been able to find that works is using the Link tag, which causes the url to show up on the bottom left hand of the screen. If I could use another element and onclick, I'd be golden.
If you are in child Component of <Route>, you should have history prop available:
<button onClick={()=>this.props.history.push('/anotherpage')} >another_page</button>
If you are not, you can pass props.history from parent element.
Or if you are deep in structure you should use withRouter HOC
Or you can create a new without path prop, so it will match always and it provide you the right history object.
<Route render={({history})=>(
<button onClick={()=>history.push('/anotherpage')} >another_page</button>
// more buttons
)} />

Categories

Resources