When I want to access props that are passed through Route
in my App.js component, in StreamEdit
component it's empty.
It must have match.params.id
.
App.js
import { Route, Routes } from 'react-router-dom';
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import './App.css';
//,BrowserRouter as Router
const App = () => {
return (
<div id='app_div'>
<HistoryRouter history={history}>
<Header />
<Routes>
<Route path='/' exact Component={StreamList} />
<Route path='/streams/new' Component={StreamCreate} />
<Route path='/streams/edit/:id' Component={StreamEdit} />
<Route path='/streams/delete' Component={StreamDelete} />
<Route path='/streams/show' Component={StreamShow} />
</Routes>
</HistoryRouter>
</div>
);
};
export default App;
StreamEdit
import React from "react";
import { connect } from "react-redux";
import { fetchStream } from '../../actions';
class StreamEdit extends React.Component{
componentDidMount() {
this.props.fetchStream(this.props.match.params.id);
}
}
const mapStateToProps = (state, ownProps) => {
console.log(ownProps)
return { stream: state.streams };
}
export default connect(mapStateToProps, { fetchStream })(StreamEdit);
I expect to achieve some data from this.props.match.params.id
.
React-Router-DOM routes don't have any props to pass. Use the useParams
hook to access the id
route path parameter. This means converting the StreamEdit
class component to a function component.
import React from "react";
import { useParams } from "react-router-dom";
import { connect } from "react-redux";
import { fetchStream } from '../../actions';
const StreamEdit = ({ fetchStream, stream }) => {
const { id } = useParams();
React.useEffect(() => {
fetchStream(id);
}, [fetchStream, id]);
...
}
const mapStateToProps = (state, ownProps) => {
console.log(ownProps)
return {
stream: state.streams
};
}
export default connect(mapStateToProps, { fetchStream })(StreamEdit);
React class component have been all but deprecated since 2019 when React hooks were released, and modern Redux no longer uses the connect
Higher Order Component, so a modern implementation would also use React-Redux's useDispatch
and useSelector
hooks.
Example:
import React from "react";
import { useParams } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { fetchStream } from '../../actions';
const StreamEdit = () => {
const dispatch = useDispatch();
const streams = useSelector(state => state.streams);
const { id } = useParams();
React.useEffect(() => {
dispatch(fetchStream(id));
}, [dispatch, id]);
...
}
export default StreamEdit;
Additionally, the Route
component's Component
prop is only helpful/useful if you are using a Data router, i.e. one created via one of the create-X-Router
utilities and rendered in a RouterProvider
. Use the element
prop instead, and the components passed as JSX. This should also help highlight why and how no props are passed to the routed components.
const App = () => {
return (
<div id='app_div'>
<HistoryRouter history={history}>
<Header />
<Routes>
<Route path='/' element={<StreamList />} />
<Route path='/streams/new' element={<StreamCreate />} />
<Route path='/streams/edit/:id' element={<StreamEdit />} />
<Route path='/streams/delete' element={<StreamDelete />} />
<Route path='/streams/show' element={<StreamShow />} />
</Routes>
</HistoryRouter>
</div>
);
};