I get the error TypeError: Cannot read properties of undefined (reading 'params')
so I try to get data detail users using id
, and when I try to see, I get the error
app.js
import React, { Component } from 'react'
import Jumbotron from './component/Jumbotron'
import NavbarComponent from './component/NavbarComponent'
import {
BrowserRouter,
Route,
Routes,
} from "react-router-dom";
import HomeContainer from './container/HomeContainer';
import CreateUserContainer from './container/CreateUserContainer';
import EditUserContainer from './container/EditUserContainer';
import DetailUserContainer from './container/DetailUserContainer';
export default class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<NavbarComponent />
<Jumbotron />
<Routes>
<Route path='/' element={<HomeContainer/>} exact />
<Route path='/create' element={<CreateUserContainer />} exact />
<Route path='/edit/:id' element={<EditUserContainer />} exact />
<Route path='/detail/:id' element={<DetailUserContainer />} exact />
</Routes>
</BrowserRouter>
</div>
)
}
}
container/DetailUserContainer.js
import React, { Component } from 'react'
import { Container } from 'react-bootstrap'
import { connect } from 'react-redux';
import { getDetailUser } from '../actions/UserAction';
class DetailUserContainer extends Component {
componentDidMount(){
this.props.dispatch(getDetailUser(this.props.match.params.id));
}
render() {
return (
<div>
<Container className='pt-3'>
<div>
<h1>Detail</h1>
</div>
</Container>
</div>
)
}
}
export default connect()(DetailUserContainer)
reducers/users.js
import { GET_LIST_USERS, GET_DETAIL_USERS } from "../actions/UserAction";
let initialState = {
getUsers: false,
errorGetUser: false,
// DETAIL USER
getDetailUsers: false,
errorGetDetailUser: false
}
const users = (state = initialState, action) => {
switch (action.type) {
case GET_LIST_USERS:
return {
...state,
getUsers: action.payload.data,
errorGetUser: action.payload.errorMessage
};
case GET_DETAIL_USERS:
return {
...state,
getDetailUsers: action.payload.data,
errorGetDetailUser: action.payload.errorMessage
};
default:
return state;
}
}
export default users;
actions/UserAction.js
import React from 'react'
import axios from 'axios'
export const GET_LIST_USERS = "GET_LIST_USERS"
export const GET_DETAIL_USERS = "GET_DETAIL_USERS"
// GET USER
export const getListUser= () => {
return (dispatch) => {
axios.get('https://my-json-server.typicode.com/baihaqiyazid/database/users')
.then(function (response) {
dispatch({
type: GET_LIST_USERS,
payload: {
data: response.data,
errorMessage: false
}
})
})
.catch(function (error) {
dispatch({
type: GET_LIST_USERS,
payload: {
data: false,
errorMessage: error.message
}
})
})
}
}
// DETAIL USER
export const getDetailUser= (id) => {
return (dispatch) => {
axios.get('https://my-json-server.typicode.com/baihaqiyazid/database/users/' id)
.then(function (response) {
dispatch({
type: GET_DETAIL_USERS,
payload: {
data: response.data,
errorMessage: false
}
})
})
.catch(function (error) {
dispatch({
type: GET_DETAIL_USERS,
payload: {
data: false,
errorMessage: error.message
}
})
})
}
}
reducers/index.js
import { combineReducers } from 'redux'
import users from './users'
export default combineReducers({
users
})
How to solve it?
CodePudding user response:
In your component did mount use this..
componentDidMount(){
// @id params
this.props.getDetailUser(1);
}
Also connect your state using mapstate..
function mapState(state) {
return {
match: state.users // which is the name you have assigned in the combine Reducer
};
}
export default connect(mapState, {getDetailUser})(DashBoard);
refer.. Class component with Redux
https://react-redux.js.org/tutorials/connect
CodePudding user response:
Before version 6, react-router-dom's Route
components passed a few routing properties to any component it rendered, for example you had a route like this:
<Route path='/' component={HomeContainer} exact />
You had access to route props inside HomeContainer
, like this:
this.props.match.params.id
In the above line, match
is one of route props, passed from Route
down to HomeContainer
.
After Version 6, (which you are using), no such thing happens. The route props are no longer passed down to children, so you don't have access to this.props.match
, or other route props (location
, etc...).
Instead, you need to use hooks in order to have access to match
, which you can't use inside Class Components. Two solutions are available:
If you want to stick to classes, Change
react-router-dom
version from v6 to v5, (then you have to use components likeRoute
according tov5
API).Get rid of Classes, instead use Functional Components, have access to hooks and keep using
react-router-dom
v6.