Home > Software engineering >  React Redux Class Component TypeError: Cannot read properties of undefined (reading 'params
React Redux Class Component TypeError: Cannot read properties of undefined (reading 'params

Time:08-14

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:

  1. If you want to stick to classes, Change react-router-dom version from v6 to v5, (then you have to use components like Route according to v5 API).

  2. Get rid of Classes, instead use Functional Components, have access to hooks and keep using react-router-dom v6.

  • Related