1

I have a number of state variables (I am only showing 3):

class IntroductionPage extends React.Component<SomePageProps, {inId: string,
  i1: string,
  i2: string
}> {
  constructor(props: any) {
    super(props);
    this.state = {inId:'',
      i1:'',
      i2:''
    };
  }

and I am reading key-value pairs from a DB:

+------------+------------+------------+
| start_type | field_name | start_text |
+------------+------------+------------+
| 0          | i1         | hi         |
+------------+------------+------------+
| 0          | i2         | it's me!   |
+------------+------------+------------+
| 0          | i3         | Schoon     |
+------------+------------+------------+


for (var key in response.data) {
  var dat = response.data[key];
  getStartType=dat['start_type']//JSON.stringify(dat['start_type']);
  for (var inner_key in dat) {
    console.log('key=' + inner_key + ' value=' + dat[inner_key]);
  }

gives

key=start_type value=0
key=field_name value=i1
key=start_text value=hi
...

Now is there any way I can loop through these retrieved value and set state, for example something like a loop or map version of this:

this.setState({dat['field_name']:dat['start_text']});

so the first row returned would be fieldname= i1, start_text ='hi' and so the loop would setState ({i1:'hi'})?

2 Answers 2

4

React Docs:

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be >batched for performance gains

don't call setState in a loop, just update a local variable inside aloop and then call the setSate method on that variable it will save you some rerenders

Sign up to request clarification or add additional context in comments.

Comments

3

As a technical question of "can I do this?" the answer is "Yes". It is ok to call setState inside a loop in your example because each state update is independent of each other and does not rely on previous values of the state. React will likely batch the setState updates together so that you won't have multiple re-renders.

for (var key in response.data) {
  var dat = response.data[key];
  this.setState({ [dat.field_name]: dat.start_text });
}

You use brackets around [dat.field_name] because it is a variable property key. But variable property names are a problem for Typescript because it assumes that they are string instead of a valid key.


I would probably do what @Sharon Geller suggests and call setState once with a combined value.

const changes = response.data.reduce(
  (acc, curr) => ({ ...acc, [curr.field_name]: curr.start_text }),
  {}
);
this.setState(changes);

Technically this doesn't require an assertion because the type of changes is the empty object {}, but you might want to assert a type on the initial value {} as State.

4 Comments

Thanks, very helpful. However I get Parameter 'prev' implicitly has an 'any' type. Any idea why?
What is prev?
oh, sorry I changed the name of acc.
It should get the type of the initial value which is {}. If you want a different type you can assert the type of the initial value like {} as State. The docs on array.reduce might help?

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.