简体   繁体   中英

ReactJS: combine 2 JSON responses from get request

So, I have this code that returns all of the data that can be retrieved from the endpoint. My endpoint has pagination: it only displays 10 datas per page. so my first endpoint: Link + "api/materials/?page=" + page; where page = 1 , returns the first 10 data. then I have a second page so the for loop will now run Link + "api/materials/?page=" + page; where page = 2 and will return a different set of datas. What I want to happen is that all the results from both endpoints will be displayed simultaneously, if I have 10 datas in my first endpoint, and 6 datas in my 2nd run of the endpoint, I want to be able to see 16 datas in my table. What happens now is that, when the loop starts and runs the first endpoint, it displays all the data from page 1, and then when it loops again and runs page 2, the data from page 1 will be replaced with page 2. I want to combine the data from page 1 and 2.

please help me.

import React, {Component} from 'react';
import { Table } from 'semantic-ui-react'
import Link from './Link';
import axios from 'axios';
import _ from 'lodash';

class Material extends Component {
    constructor(props){
      super(props);
      this.state={
        materials: []
    }
   }

   componentDidMount() {
    const token = localStorage.getItem('jwt');
    const total = localStorage.getItem('totalpage');
    var page;
    for (page = 1; page <= total ; page++) {
        const apiBaseUrl = Link + "api/materials/?page=" + page;

        const config = {
         headers: {
           'Authorization': "bearer " + token,
           'Accept': 'application/json',
           'Content-Type': 'application/json',
         }
        }

        axios.get(apiBaseUrl, config)
         .then((response) => {
             console.log(response.data);
            this.setState({
             materials: response.data
           })
          })
    }

   }

    render() {
        const { materials } = this.state;

        let returndata = _.isEmpty(materials) ? [] : materials.data

        return (  
            <div className="ui container"> 
            <br />
            <br />
                <Table fixed>
                    <Table.Header>
                        <Table.Row>
                            <Table.HeaderCell>UUID</Table.HeaderCell>
                            <Table.HeaderCell>Title</Table.HeaderCell>
                            <Table.HeaderCell>Description</Table.HeaderCell>
                        </Table.Row>
                    </Table.Header>

                    <Table.Body>
                    {returndata.map((item, i) => {
                        return (
                        <Table.Row key = {i}>
                            <Table.Cell>{item.uuid}</Table.Cell>
                            <Table.Cell>{item.title}</Table.Cell>
                            <Table.Cell>{item.description}</Table.Cell>
                        </Table.Row>
                        )
                    })}
                    </Table.Body>
                </Table>
            </div>
      );
    }
  }
  export default Material;

Looking at your componentDidMount method. You can extend the current state object property instead of replacing it like this:

componentDidMount() {
  const token = localStorage.getItem('jwt');
  const total = localStorage.getItem('totalpage');
  var page;
  for (page = 1; page <= total ; page++) {
    const apiBaseUrl = Link + "api/materials/?page=" + page;

    const config = {
       headers: {
         'Authorization': "bearer " + token,
         'Accept': 'application/json',
         'Content-Type': 'application/json',
       }
    }

    axios.get(apiBaseUrl, config)
     .then((response) => {
        console.log(response.data);
        this.setState((prevState) => ({
          materials: prevState.materials.concat(response.data)
        }));
      })
  }
}

Replace your .then of axios with this

.then((response) => {
        let tempState = [...this.state.materials];
        tempState.push(response.data)
        this.setState({
         materials: tempState
       })

This will copy the state to another variable and push the new data into the new variable ( tempState ) and replace the state with tempState which now contains the previous state data and the new data

That's because you're replacing the materials object in the state with the newly returned data.

Call some function which will update your state.

axios.get(apiBaseUrl, config)
.then((response) => {
    console.log(response.data);
    this.updateMaterials(response.data);
 })

Now update your state in that function as First retrieve the old list and then concat the new list in it, and then store it to your state.

updateMaterials = (data) => {
    let updatedList = this.state.materials.slice();
    updatedList = updatedList.concat(data);
    this.setState({materials: updatedList});
}

Also remove data from materials.

change

let returndata = _.isEmpty(materials) ? [] : materials.data

to

let returndata = _.isEmpty(materials) ? [] : materials

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM