ReactRouter: Pass data/object in <Link> - javascript

I'm fairly new to React and ReactRouter. I've got basic routing down, and am now trying to pass an object from one component to a sibling component using Link.
I've spent hours and hours here on SO, and viewing other tutorials, but none of the code I've tried works. I either get an error on the receiving component, or no errors, but then the data I'm supposedly sending is undefined. I have a feeling I'm missing something very basic.
Can someone either post a very simple working example of sending an object via Link, and using that data in a sibling component? Or, point to an existing working example on StackBlitz or something similar?
I'm using functional components, React v. 16.13.1, and react-router-dom v. 5.2.0 (version taken from package.json).
Thanks in advance for any and all help!

Here is an example for you:
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useLocation
} from "react-router-dom";
Navigating from Sibling1 to Sibling2:
<Link to={{pathname: "/path_of_sibling2", state: "this data would be sent" }}>Sibling 2</Link>
Or you can pragmatically push like:
history.push({pathname: "/path_of_sibling2", state: "this data would be sent" });
Now in Sibling 2, you can recover this state like this:
const {state} = useLocation();
return (
<p>{state}</p>
);

Related

React - Change URL for modal that can be open everywhere

I'm new in React and I was asked to implement this feature in an App mostly done. So, I don't want to destroy everything.
I have a modal containing components login/register/activation/password-recovery/password-reset according the situation. This modal can appear on every single public page. It's possible to navigate in the modal from login to register, from login to password-recovery, from password-reset to login.
We can access to the modal from a link in he header and from other links through the site. The modal appears with an animated transition.
I was asked to change the URL according to the modal content displayed.
The URLs must be:
site.com/en/login
site.com/en/register
site.com/en/activation
site.com/en/password-recovery
site.com/en/password-reset
The page behind the modal should remains even if the URL was site.com/en/page1/info1/[...] or the homepage should be displayed by default behind the modal on direct URL access/refresh.
I found many pieces for this puzzle on the web, but pieces don't seem to fit together. I just want to know the best way to achieve this task.
I don't have convincing code to show right now.
If that can help, it's a React-Redux App using JSX on NodeJS server.
if your component is rendered via Router you can use history.push(), else you can wrap your component with withRouter from react-router-dom and then use history.push(),
import { withRouter } from 'react-router'
const myComponent = () => {
...
}
// by this history is going to be available from props in this component
export default withROuter(myComponent)
if neither of then was not working , you still have location object from window of browser left , try that....
Maybe the 'history' library can help you easily
https://www.npmjs.com/package/history
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.listen((location, action) => {
// location is an object like window.location
console.log(action, location.pathname, location.state)
})

React Router changing params doesn't fire componentWillRecieveProps

The Problem: Changing the parameters of a <Route /> component does not update the component it is rendering. The route change is shown in the URL bar, but directly rendering {this.props.match.params.id} shows the old :id and not the new one reflected in the URL bar.
Update: I fixed this by moving the <BrowserRouter /> out from the index.js file and into the App.js file. It is no longer the direct child of Provider and is instead the child of the App component. No clue why this makes everything suddenly work.
What I am doing: I have a <Link to="/user/11" /> that goes from user/7 (or any current ID) to a /user/11
The componentWillReceiveProps(newProps) of the component it is rendering is not fired.(This component is connected using react-redux if that helps any. I tried applying withRouter around the connection and that did not help)
If I manually refresh the page in chrome (using CTRL-R or the refresh button) the page shows the new data, rendering the "new" param.
TLDR: Switching from /user/7 to /user/11 does not fire that componentWillRecieveProps function and therefore leaving the component displaying the old state
Question: What am I doing incorrectly here that causes componentWillReceiveProps to not fire.
I am using react-router v4 and the latest create-react-app
This is my CWRP function:
componentWillReceiveProps(newProps) {
console.log("getProps")
this.props.getUser(newProps.match.params.id)
if (newProps.match.params.id == newProps.currentUser.id) {
this.setState({ user: "currentUser" })
} else {
this.setState({ user: "selectedUser" })
}
}
This is the full code of my component: https://gist.github.com/Connorelsea/c5c14e7c54994292bef2852475fc6b43
I was following the solution here and it did not seem to work for me. Component does not remount when route parameters change
You'll need to use React Router Redux

React router not reloading Component when changing url params

I know that it's not a default behaviour / feature of react-router to help us reload easily the current component but I really need this in my application.
My application deals with products. I have a product list that I can load, and when I click on an item, it displays the concerned product details.
On that page, I have related product links that load the same component, but with another product details, located at
<Route path="/products/:id/details" component={ProductDetail} />
I m fetching data in my componentWillMount, and it seems that if I only change the URL, a new component is NOT mounted, and so, I m always having my old data displayed, without fetching anything.
As a beginner using React, I'm looking for some help, or some tricks to reload the component concerned by that page. I mean being able to reload the ProductDetail with the good product.
I tried to look around with componentWillUpdate (a method in which I can see that the router URI changes :D) but I can't setState inside of it to make my component reload (it doesn't seem to be a good practice at all)
Any idea how can I make this work ?
EDIT : According to the first answer, I have to use onEnter. I m now stuck with the way of passing state/props to the concerned component :
const onEnterMethod = () => {
return fetch(URL)
.then(res => res.json())
.then(cmp => {
if (cmp.length === 1) {
// How to pass state / props to the next component ?
}
});
};
The way to handle it depends if you are using flux, redux or however you want to manage your actions. On top of it I would try to make use of onChange property of Route component (check React router docs):
<Route path="/products/:id/details" component={ProductDetail} onChange={someMethod} />
And then in the someMethod create the action if you are using redux or however is done in flux.
The redux would be:
<Route path="/products/:id/details" component={ProductDetail} onEnter={onEnterHandler(store)} />
And the onEnterHandler with the redux store:
function onEnterHandler(store) {
return (nextState, replace) => {
store.dispatch({
type: "CHANGEPRODUCT",
payload: nextState.params.id
})
};
}
And then in your ProductDetail component you would print the new information (It would require a bit more of learning in redux and redux-sagas libraries to complete that part).
Keep in mind that React is just the view part, trying to solve all those problems using only react is not only not recommended but also would mess up your code.

How to use js code to forward reactjs-router?

when u seem to require forward in reactjs we used to put a Link or button ,and then consumer click it ,then the page reload corresponding path of router . Now,I want the page turn to other path of router when I request a post and the status of response is 200. It can't use a link or button ,could reactjs use code to do this? like : CertainComponent.setPath(otherPath); CertainComponent.turn;
My English is poor , it may be not clear to delive the function which i want to do.
Thanks!
I think you want to use this.context.router.push('/users/12')
https://github.com/reactjs/react-router/blob/master/docs/API.md#routercontext
First of all the component you are using has to be a container, which means you have to create it with connect() so it has access on store and dispatch:
let MyComponent = ({ dispatch, store }) => {
store.routing.push('url');
}
export default connect()(MyComponent)
And this depends how you named the router key on your store when you combined the routing reducer from redux-router on your store.
There is also another alternative, where you could do
import { hashHistory } from 'react-router';
hashHistory.push('next-url');

Get current page path from react-routers browserHistory object

Outside of my components I need to query the current active URL. I'm going to set some classes on the body ( which is outside my react root ) based on this.
First attempt was to use
//Gets an array of class names that I can add to my body tag
getClassNames(window.location.pathname);
But it seems window.location.path isn't updated when React Router navigates. Surprising yes.
So I thought, ok maybe I can get this from browserHistory
import { browserHistory } from 'react-router'
But alas, I can't see a way to read the current page path from here either ( no decent API documentation seems to exist for this object)
Any tips? Seems like a simple problem, and it would be if window.location.pathname stayed in sync with the history object.
Ok as of 2017 at least, location is available via
browserHistory.getCurrentLocation();
const location = browserHistory.getCurrentLocation();
console.log(location);
The only way I know to do this right now is to use a listener like
import { browserHistory } from 'react-router'
browserHistory.listen(function(event) {
//manage the pathname on your own
console.log(event.pathname);
});
Not ideal, but even after looking at the DOMUtils library used by history, its implementation of getWindowPath() includes the pathname, search, and hash strings. However, looking for a docs link for you on GitHub, History seems to have received a v3 rewrite as of ~20 days ago and now includes a pathUtils module that may be useful to you.

Categories

Resources