Felipe Olaya Ospina
Felipe Olaya Ospina

Reputation: 103

Problem using multiple Reducers and Actions Redux

I have a little problem. I have diferent reducers in different files using a combine reducer, but when i try to use the "different" INITIAL STATES on these reducers it doesnt apear

For example

Product Reducer -> This is the state that i have to take

const INITIAL_STATE = {
    productosInventario: [],
    loading: false,
    error: ''

Category Reducer -> this is the state for these reducer

const INITIAL_STATE = {
    categorias: [],
    categoriaActual: '',
    loading: false,
    error: ''
}

The idea is use both on these component:

Component:


import React, { Component } from 'react'
/* Components */
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import CardItemInventario from '../components/inventario/CardItemInventario'
import * as ProductoActions from '../actions/ProductoActions'
import * as CategoriasActions from '../actions/CategoriasActions'
/* Styles */
import Spinner from '../components/Spinner'
import Fatal from '../components/Fatal'
import '../assets/styles/Containers/Inventario.scss'

class Inventario extends Component {

    async componentDidMount() {
        await this.props.traerTodosLosProductos();
    }

    handleChangeCategoria = (e) => {
        this.props.cambioCategoriaInventario(e.target.value)
        this.props.traerProductosPorCategoriaInventario(e.target.value)
    }

    /* Mapea todas las categorias disponibles en base de datos */
    traerCategoriasInventario = () => this.props.categoriasInventario.map(category => {
        let categori = category.categoria
        return (
            <option
                value={categori}
            >
                {categori}
            </option>
        )
    })


    ponerContenido = () => {
        if (this.props.loading) {
            return (
                <Spinner />
            )
        }
        if (this.props.error) {
            return (
                <Fatal
                    error={this.props.error} />
            )
        }
        return (
            <>
                <div className="button-add__cont">
                    <h1 className="button-add__title">
                        Inventario
                    </h1>
                    <Link to='/agregarinventario' className="button-add__cont--link">
                        Agregar a Inventario
                    </Link>
                </div>
                <select
                    name="categoriaSelect"
                    id=""
                    onChange={this.handleChangeCategoria}
                    className="selector-categoria"
                >
                    <option value='' defaultValue> - Categoria -</option>
                    {this.traerCategoriasInventario()}
                </select>
                <div className="inventario-cont">
                    
                    {this.imprimirProductos()}
                </div>
            </>
        )
    }

    imprimirProductos = () => this.props.productosInventario.map(Productos =>
        <CardItemInventario
            nombre={Productos.nombre}
            marca={Productos.marca}
            cantidad={Productos.cantidad}
            distribuidor={Productos.distribuidor}
            precio={Productos.precio}
        />
    )



    render() {
        console.log(this.props)
        return (
            <>
                {this.ponerContenido()}
            </>
        )
    }
}

const mapStateToProps = (reducers) => {
    return (
        reducers.ProductoReducer,
        reducers.CategoriasReducer
    )
}

const mapDispatchToProps = {
    ...ProductoActions,
    ...CategoriasActions
}

export default connect(mapStateToProps, mapDispatchToProps)(Inventario);

actions ->

productoActions:

import axios from 'axios'
import {
    TRAER_TODOS_LOS_PRODUCTOS
} from '../types/ProductoTypes'
import { host_name, port_redux } from '../../../config'
import { CARGANDO, ERROR } from '../types/GlobalTypes'

const axiosConf = {
    baseURL: `http://${host_name}:${port_redux}`
}
export const traerTodosLosProductos = () => async (dispatch) => {
    dispatch({
        type: CARGANDO
    })
    try {
        const res = await axios.get(`/api/productos/get/listar`, axiosConf)
        dispatch({
            type: TRAER_TODOS_LOS_PRODUCTOS,
            payload: res.data
        })
    } catch (error) {
        console.log("Error: " + error)
        dispatch({
            type: ERROR,
            payload: error.message
        })
    }

}


export const traerProductosPorCategoriaInventario = (categoria) => async (dispatch) => {
    try {
        const res = await axios.get(`/api/cotizacion/get/productosporcategoria/${categoria}`, axiosConf)
        dispatch({
            type: TRAER_TODOS_LOS_PRODUCTOS,
            payload: res.data
        })
    } catch (error) {
        console.log("Error: " + error)
        dispatch({
            type: ERROR,
            payload: error.message
        })
    }

}

categoryActions_ >

import axios from 'axios'

import { host_name, port_redux } from '../../../config'
import { CARGANDO, ERROR } from '../types/GlobalTypes'
import {
    LISTAR_CATEGORIAS,
    CATEGORIA_ACTUAL
} from '../types/CategoriasTypes'

const axiosConf = {
    baseURL: `http://${host_name}:${port_redux}`
}

export const traerCategoriasInventario = () => (dispatch) => {
    const res = axios.get(`/api/categorias/get/listar`, axiosConf)
    console.log(res)
    dispatch({
        type: LISTAR_CATEGORIAS,
        payload: res.data.data
    })

}

export const cambioCategoriaInventario = (categoria) => async (dispatch) => {
    try {
        dispatch({
            type: CATEGORIA_ACTUAL,
            payload: categoria
        })
    } catch (error) {
        console.log("Error: " + error)
        dispatch({
            type: ERROR,
            payload: error.message
        })
    }
}

Upvotes: 0

Views: 445

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42160

const mapStateToProps = (reducers) => {
    return (
        reducers.ProductoReducer,
        reducers.CategoriasReducer
    )
}

It seems like you are having some confusion between state and reducer. The state is the object which contains all of your data. It is just a plain javascript object. The reducer is a function which takes the state object and an action and returns a new state object.

Your setup should look something like this:

const productoReducer = (state = INITIAL_PRODUCTOS, action ) => {
  switch ( action.type ) {
    case 'TRAER_TODOS_LOS_PRODUCTOS':
      /* ... code here ... */
    default:
      return state;
  }
}

const categoriasReducer = (state = INITIAL_CATEGORIAS, action ) => {
  switch ( action.type ) {
    case 'LISTAR_CATEGORIAS':
      /* ... code here ... */
    default:
      return state;
  }
}

export const reducer = combineReducers({
  producto: productoReducer,
  categorias: categoriasReducer,
})

Here we have two separate reducers for categories and for products, and each gets a separate initial state. We use combineReducers to put them together so now the combined state has properties producto and categorias.

Your component Inventario needs to access a bunch of values from state: categoriasInventario, productosInventario, loading, and error. Rather than passing the state into the component, we use mapStateToProps to extract these values and pass them as props.

const mapStateToProps = (state) => {
    return {
        categoriasInventario: state.categorias.categorias,
        productosInventario: state.productos.productosInventario,
        loading: state.categorias.loading || state.productos.loading,
        error: state.categorias.error || state.productos.error,
    }
}

Upvotes: 1

Related Questions