Blueprint
Blueprint

Reputation: 442

component not re-renders as expected when redux store updates

in my react-redux app one of the components is rendering "box" components according to a number passed down as props through the store. the number is controlled by a slider controlled component, that for sure changes the store as i can see with my redux dev tools.

at first render the component renders the boxes as expected inside their wrapper div, but as soon as i move the slider and change the number all i get is a single box component.

i've tried to change the component into a stateful one and use different hooks but so far without success.

here is the component:

import React from 'react';
import { connect } from 'react-redux'; 
import Box from './Box';

const Grid = ({ boxNumber }) => {

    return(
        <div className='flex flex-wrap'>
            {new Array(boxNumber).fill(null).map((box, i) => <Box key={i} />)}
        </div>
    )
}

const mapStateToProps = (state) => ({
    boxNumber: state.boxNumberReducer.boxNumber
})

export default connect(mapStateToProps)(Grid);

i'm adding here the reducer and action just in case even though i don't believe that's where the issue is, but maybe i'm missing something.

reducer:

import { SET_BOX_NUMBER } from '../actions/constants';

const initialState = {
    boxNumber: 100
}

export default (state = initialState , {type, payload}) => {
    switch (type) {
        case SET_BOX_NUMBER:
            return {...state, boxNumber: payload};
        default:
            return state;
    }
}

action:

export const setBoxNumber = (payload) => ({
    type: SET_BOX_NUMBER, payload
})

here is the box component, i'm using tailwindcss so it's basically a div with height and width of 2rem, a border and a white background color:

import React from 'react';

const Box = () => {
    return(
        <div className='w-8 h-8 border border-black bg-white'>
        </div>
    )
}

export default Box;

EDIT: this is the slider component where the action is being dispatched:

import React from 'react';
import { connect } from 'react-redux';
import { setBoxNumber } from '../actions';

const Slider = ({ boxNumber, handleChange }) => {
    return(
        <div className='slider p-1 m-1'>
            <div className='flex justify-center'>
                {boxNumber}
            </div>
            <div className='flex justify-center'>
                <input 
                    onChange={handleChange}
                    value={boxNumber}
                    type="range" 
                    step='10'
                    min="10" 
                    max="500" 
                />
            </div>
        </div>
    )
}

const mapStateToProps = (state) => ({
    boxNumber: state.boxNumberReducer.boxNumber
});

const mapDispatchToProps = {
    handleChange: (event) => setBoxNumber(event.target.value)
}

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

Upvotes: 0

Views: 62

Answers (1)

zb22
zb22

Reputation: 3231

You need to convert event.target.value to Number in your Slider component, because you are passing the value as string to new Array(boxNumber)

const mapDispatchToProps = {
    handleChange: (event) => setBoxNumber(Number(event.target.value))
}

Upvotes: 1

Related Questions