0

I'm trying to edit an object and replace it in array using React and Redux like this:

case EDIT_LANGUAGE:
  let languages = [...state.languageSkills];
  languages[languages.findIndex(el => el.id === action.payload.id)] = action.payload;
  return {
    ...state,
    languageSkills: languages
  };

'languages' array looks find before return statement, but state is not re-rendered. I guess I'm mutating state somehow. Other actions (delete, get, set) are working fine. Any tips?

EDIT. This is relevant part of the component that should render

import { setLanguages, getLanguages } from '../../actions';
import {connect} from 'react-redux';
import {bindActionCreators} from "redux"
import React, { Component } from 'react';

class UserProfile extends Component {
  constructor(props) {
    super(props);
  }

  render() {   
    const languageSkillItems = this.props.languageSkills.map((languageSkill) => {
      return (
        <LanguageSkillItem key={languageSkill.id} item={languageSkill} />
      )
    });

    return (
        <div className="profile">            
            <Language languageSkillItems={languageSkillItems} />            
        </div>
    )
    } 
}

const mapStateToProps = (state) => {
  return {
    languageSkills: state.languageSkills
  };
};


const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators({ setLanguages, getLanguages }, dispatch)
  }
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(UserProfile

);
4
  • how payload is created - new object ? Commented Sep 11, 2018 at 20:15
  • dashton answer is correct. A basic rule to follow is to avoid mutation in redux => Never mutate the state Commented Sep 11, 2018 at 21:37
  • I take it render is being triggered? what does <Language /> look like? Commented Sep 12, 2018 at 10:16
  • 1
    Render was actually not triggered. I've to some refactoring tomorrow, the whole design is pretty... not so good. Commented Sep 12, 2018 at 17:15

1 Answer 1

3

You need to create a new array reference, easiest way is just to use map, like so:

case EDIT_LANGUAGE:
  const languageSkills = state.languageSkills.map(el => {
    if(el.id === action.payload.id) {
        return action.payload;
    }
    return el;
  });
  return {
    ...state,
    languageSkills
  };
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I didn't know that I also need a new array reference. Unfortunately re-rendering is still not working...
OK, you need to post your code (preferably runnable), it could be many other things. e.g. your react-redux connect logic may not be behaving as you expect because of nesting etc etc.
I accept this as an answer. My core problem was elsewhere, but answering to your questions lead me to right direction. The application had deeply nested components and one used state which was set in constructor. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.