0

I have an object array that I'm outputting to a form of inputs. These inputs need to be updated, the values rendered to show the changes. I'm able to console the key and new value but the error I receive is that metafields.map is not a function.

My code is as follows:

class EditMetafields extends React.Component {
  constructor(props) {
    super(props);
    this.state = { metafields: [] }
  }

  componentDidMount() {
    // retrieving data from the db to populate metafields
    metafields = [
      {id: 0, key: "key0", value: "value0"},
      {id: null, key: "keyNull", value: "valueNull"},
      {id: 2, key: "key2", value: "value2"},
    ]

    this.setState({ metafields: metafields });
  }

  render() {
    const { metafields } = this.state;
    const formFields = metafields.map((props) => 
      <TextField 
        key={props.id} 
        label={props.key} 
        id={prop.id} 
        value={props.value} 
        changeKey={props.id} onChange={(val) =>{
          console.log(props.key, val); //returns accurate output i.e. "key0 value0a" when 'a' key pressed
          this.setState({ metafields: { ...this.state.metafields, [props.key]: val } }) //TypeError: metafields.map is not a function after 'a' key pressed
        }
      } />
    );

    return (
     <Page>
       <Form>
         {formFields}
       </Form>
     </Page>
    )
  }
}

When it was an array of object containing a single key/value pair I was able to pair and change without issue but now that I have to attach ids and more to the object React gets upset with Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.

I need to work with objects containing id, namespace, key, and value and output each object to a input within a form that can be updated but I'm not sure if I'm using React properly by assigning metafields to props. Links to relevant articles or a point in the right direction would be much appreciated!

1 Answer 1

1

As Brian mentioned, this line:

this.setState({ metafields: { ...this.state.metafields, [props.key]: val } })

changes the metafields state variable into an object. What I think you're trying to do, is update an element's value in the metafields array, based on key.

To accomplish this, you should use map and use the callback variant of setState (since you're depending on the previous state of metafields):

this.setState(prevState => {
    return { metafields: prevState.metafields.map(metafield => {
        if (metafield.key === props.key) {
            metafield.value = val;
        }
        return metafield;
    })};
});

This code will update the correct element in the metafields array with the new value.

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

2 Comments

Thank you, I have never used prevState, it's going into the toolkit.
Followup question on this; if I'm seeking to update and element's value in an array without keys would I need only compare the index?

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.