0

I'm trying to use this.setState on an array of objects once I've received the data, however, my code below only sets the state on 1 object. I think it's writing over itself.

Path: MongoDB

"careerHistoryPositions": [
    {
      "company": "Company A",
      "title": "Title A",
      "uniqueId": "1497575516964"
    },
    {
      "company": "Company B",
      "title": "Title B",
      "uniqueId": "1497575525034"
    }
  ]

Path: Reactpage

constructor(props) {
    super(props);

    this.state = {
      data: [],
    };
  }

componentWillReceiveProps(nextProps) {
    const profileCandidateCollection = nextProps.profileCandidate;
    const profileCandidateCollectionId = profileCandidateCollection._id;
    const careerHistoryPositions = profileCandidateCollection && profileCandidateCollection.careerHistoryPositions;

    if(careerHistoryPositions) {
      careerHistoryPositions.map((position) =>
      this.setState({
        data: [{
          'position.uniqueId': position.uniqueId || '',
          'position.company': position.company || '',
          'position.title': position.title || ''
        }]
      })
      );
    }
  }
bp123
  • 3,217
  • 8
  • 35
  • 74
  • You *are* changing the value of `data` from an array to an object. That's what you are telling JavaScript to do. What do you want to happen instead? Maybe you mean to do `this.setState({data: careerHistoryPositions.map(...)})` instead? – Felix Kling Jun 16 '17 at 01:39
  • Now you are telling JavaScript to set `data` to an array with a single object. There is no magic happening here. `data` will be exactly what you are setting it to. – Felix Kling Jun 16 '17 at 01:42
  • There are an unknown number of `careerHistoryPositions` that need to be mapped. It could be 1 or it could be 20. I need to set the state of data so I can use a form. – bp123 Jun 16 '17 at 01:45
  • As I mentioned in my first comment, if you want to assign the result of the `.map` function to `data` then that's exactly what you need to do: `this.setState({data: careerHistoryPositions.map(...)})`. But haven't explained yet what you actually expect to happen. – Felix Kling Jun 16 '17 at 01:47
  • This is a follow on question from https://stackoverflow.com/questions/44534473/form-errors-with-handleinputchange-in-component/44535156#44535156 . My component doesn't render anything becuase this.state.data is empty with it renders. I'm trying to fill this.state.data with some data. – bp123 Jun 16 '17 at 01:50
  • Your code will do that (assign a value to `data`)... but I guess you are not getting the result you want. Again, if you want the result of `.map` to be assigned to `data` do `this.setState({data: careerHistoryPositions.map(positions => { return {...}})})`. If you want something else you have to explain precisely what it is you want. I.e. what is the value you want `this.state.data` to hold? Can you provide an example? – Felix Kling Jun 16 '17 at 01:54

2 Answers2

1

Note that set state is not invoked immediately and secondly, you are overwriting data with new state. And secondly setting State multiple times would re-render which is inefficient.

Too stop overwriting, you can use the spread operator. Example:

a = [1,2,3]
b = [...a, 4,5]
//b = [1,2,3,4,5]

So to translate this to your code, it would look like this:

this.setState({
        data: [...this.state.data, {
          'position.uniqueId': position.uniqueId || '',
          'position.company': position.company || '',
          'position.title': position.title || ''
        }]
      })

This is still inefficient as you are calling state multiple times. I would change it to look like this:

if(careerHistoryPositions) {
      const newData = careerHistoryPositions.map((position) =>
      ({
            'position.uniqueId': position.uniqueId || '',
            'position.company': position.company || '',
            'position.title': position.title || ''
      }));
      this.setState({
          data: newData
      })
}
Shayan C
  • 1,510
  • 1
  • 13
  • 21
0
 if(careerHistoryPositions) { 
    const data = [ ];
    careerHistoryPositions.map((position) =>
    data.push(
{
 'position.uniqueId': position.uniqueId || '',
 'position.company': position.company || '',
 'position.title': position.title || '' 
})
);

     this.setState({ data, }); 
    }

This should work.. I think this method would be better rather than setting the state multiple times within the map function..

JiN
  • 818
  • 1
  • 7
  • 14