Reputation: 65
When I try to navigate from one component to another page using routes and need to pass some parameters across with it. I have tried providing them as state using history.push(..) as seen below but it doesn't work, both state and props are empty.
In the holder component, Holder.js
At top:
import history from '../routes/history';
In render function
<Button variant="contained" onClick={() => { history.push('/share', {
account: this.props.account, credential: JSON.stringify(this.state.credentialInfo)});
window.location.reload();}} fullWidth sx={{mt: 3, mb: 2}}>Share ID</Button>
In index.js
ReactDOM.render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/share" element={<SharePage />} />
</Routes>
</BrowserRouter>,
document.getElementById('root')
);
In history.js
import { createBrowserHistory as history} from 'history';
export default history();
Upvotes: 1
Views: 394
Reputation: 202836
It appears you are using react-router-dom
version 6. In RRDv6 imperative navigation is accomplished via a navigate
function returned from the useNavigate hook. The issue is that the RRDv6 BrowserRouter
component instantiates and maintains its own internal history
object and state. You can create your own, but since it's a separate history context it won't work with your router, routing, and navigation.
declare function useNavigate(): NavigateFunction; interface NavigateFunction { ( to: To, options?: { replace?: boolean; state?: any } ): void; (delta: number): void; }
Import the useNavigate
hook and access the navigate
function, sending along state with the route transition. Route state is part of the options object as the second parameter to the navigate
function.
This is only validly used in function components though, and the component using the button appears to be a class component. You can either convert the class component to a function component or create your own custom withNavigation
Higher Order Component so the navigate
function can be injected as props.
import { useNavigate } from 'react-router-dom';
const withNavigation = Component => props => {
const navigate = useNavigate();
return <Component {...props} navigate={navigate} />;
};
export default withNavigation;
Import the new HOC and decorate your class component, accessing the navigate
function from props.
import withNavigation from '../withNavigation';
...
<Button
variant="contained"
onClick={() => {
this.props.navigate(
'/share',
{
state: {
account: this.props.account,
credential: JSON.stringify(this.state.credentialInfo),
}
},
);
}}
fullWidth
sx={{ mt: 3, mb: 2 }}
>
Share ID
</Button>
...
export default withNavigation(MyClassComponent);
Route state is accessed the same way in v6 as it was in v5, save for the location
object being a prop. Use the useLocation hook to access the location
object and its state
property.
const { state } = useLocation();
...
const { account, credential } = state || {};
If SharePage
is another class component then you can expand your withNavigation
HOC to include other RRD hooks and inject other props.
Upvotes: 1
Reputation: 290
No. you can only:
import { useHistory } from 'react-router-dom';
function YourComponent() {
const history = useHistory();
const share = useCallback(() => {
history.push(`/share?account=${this.props.account}&credential=${JSON.stringify(this.state.credentialInfo)}`);
}, []);
return (
<Button variant="contained" onClick={share}>Share ID</Button>
)
}
`
Upvotes: 0