0

I'm trying to set state while adding a key value to the array. I've followed several questions including this one: How to add a new key value to react js state array?

I can't get any of those answers to work with my challenge.

My state is like this:

this.state = { jsonReturnedValue: [] }

when componentDidMount() I make a fetch request and I added new state and a foreach loop (as based on the instructions from the question above)

  componentDidMount() {

    let newState = [...this.state.jsonReturnedValue];
    newState.forEach(function(file) {
      file.selected = "false"
    })

    fetch('http://127.0.0.1:8000/api/printing/postcards-printing')
      .then(response => response.json())
      .then(json => {
      this.setState({ jsonReturnedValue: [...this.state.jsonReturnedValue, ...json.printCategory.products] }, () => console.log(this.state));
      })
      .then(this.setState({jsonReturnedValue: newState}, () => console.log("selected added" + this.state) ));
  }

I was thinking that I would just setState again with the key value pair so I added the .then the third time but it's not working.

the final console log returns this: selected added[object Object] Digging more into it I see the object is empty.

EDIT: My goal is to set the state with the api call but also add key value of "selected: false" to each array.

5
  • 1
    the console log will look like that no matter what because you're trying to concatenate a string and an object. so if you change the log to console.log('selected added', this.state) does it still come back incorrect? Commented Oct 24, 2018 at 22:15
  • Not much of this makes sense. You just want to set the state when the fetch call completes? Commented Oct 24, 2018 at 22:19
  • My goal is to add the api call to state but also add the key / value of "selected: false" to each array @Jared Smith Commented Oct 24, 2018 at 22:21
  • .then(this.setState your using then incorrectly, then expects a function callback. eg.. .then(() => this.setState(.... Commented Oct 24, 2018 at 22:26
  • 1
    you should describe in your question what kind of data structure gets returned from the api and what should state look like after it's updated Commented Oct 24, 2018 at 22:29

4 Answers 4

2

componentDidMount only runs once, the first time the component is mounted, which is before your data call. After you fetch your data and call setState, the update lifecycle methods are run.

Assuming you are on a new version of React, you'll want to intercept your state change in getDerivedStateFromProps:

getDerivedStateFromProps(props, state) {
  // `state` will be the new state that you just set in `setState`
  // The value returned below will be the new state that the `render`
  // method sees, and creating the new state here will not cause a re-render
  return state.jsonReturnedValue.map((file) => {
    file.selected = "false";
    return file;
  });
}

Now, Ideally you don't actually want to do that there, but instead do it once you fetch your data:

fetch('http://127.0.0.1:8000/api/printing/postcards-printing')
      .then(response => response.json())
      .then(json => {
        // NOTE: it's unclear from your post exactly what the data structure is
        // Is it product.file, or is `product` also `file`?
        const products = json.printCategory.products.map((product) => {
          product.file = "selected";
          return product;
        });

        this.setState(
          {
            jsonReturnedValue: [...this.state.jsonReturnedValue, ...products],
          },
          () => console.log(this.state)
        );
      });
Sign up to request clarification or add additional context in comments.

Comments

0

should probably be something like this

function addSelectedFalse(array) {
    return array.map(item => ({
        ...item,
        selected: false
    })

fetch('endpoint')
    .then(response => response.json())
    .then(json => this.setState({ jsonReturnedValue: [...addSelectedFalse(this.state.jsonReturnedValue), ...addSelectedFalse(json.printCategory.products] }))

Comments

0

From my understanding you want to fetch a products array and add selected: false to each product before setting state:

constructor(props) {
    super(props);
    this.state = {
        products: []
    }
}
componentDidMount() {
    fetch('http://127.0.0.1:8000/api/printing/postcards-printing')
    .then(response => response.json())
    .then(json => {
        const { products } = json.printCategory;
        for (let i = 0; i < products.length; i++) {
            products[i].selected = false;
        }
        this.setState({products});
    });
}

Comments

0

Here an idea working:

https://codepen.io/ene_salinas/pen/GYwBaj?editors=0010

  let { Table } = ReactBootstrap;

  class Example extends React.Component {
    constructor(props, context) {
      super(props, context);

      this.state = {
          products: []
      }
    }

    componentDidMount() {
      console.log('componentDidMount..')
      fetch('https://api.github.com/users/xiaotian/repos')
        .then(response => response.json())
        .then(output => {
          let products = []
          for (let i = 0; i < output.length; i++) {
              products.push({selected:false,name:output[i].name})
          }

          this.setState({products},() => console.log(this.state))

      })

    }

    render() {

          return(<Table striped bordered condensed hover>
            <thead>
              <tr>
                <th>Selected</th>
                <th>Name</th>
              </tr>
            </thead>
            <tbody>
              {this.state.products.map((item, i) => {
                return (
                    <tr><td><input type="checkbox" checked={item.selected}/></td><td>{item.name}</td></tr>
                ) 
              })}
            </tbody>
          </Table>)
    }
  }

  ReactDOM.render(
    <Example />, 
    document.getElementById('app')
  );

Hope to help you!

Comments

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.