Kaji Toon
Kaji Toon

Reputation: 65

How can i merge two state into single state in React Hooks?

I want to merge two state named Data and District value and create a single state named test.Since i am fetching two states value from different API.I cannot make a single state merging the data of the following states,i tried but when i tried to merge two state value a single states value i get but next state value cannot be obtained,since i tried to use spread operator but still cannot solve the issue.Following below are my code:Please help for solution:

import React, { useState, useEffect } from 'react';
 import Axios from 'axios';

export default function Testmap() {
const [Data, setData] = useState([]);//fetched data
const [isLoading, setIsloading] = useState(true);
const [District, setDistrict] = useState([]);
const [test, setTest] = useState({
    data: [],
    districts: []
});





useEffect(() => {
    //fetching data from api 
    Axios.get('https://covid19wst.yilab.org.np/api/v1/form')
        
        .then(res => {
            setData(res.data)
            setTest({ ...test, data: res.data })
            setIsloading(false)

        })
        .catch(err => {
            console.log(err);
        })
    Axios.get('https://bipad.gov.np/api/v1/district/')
        .then(res => {
            setDistrict(res.data.results)
            setTest({ ...test, districts: res.data.results })



            setIsloading(false)

        })
        .catch(err => {
            console.log(err);
        })

}, [])




console.log(isLoading);
console.log("data", Data);
console.log("districts>>", District);
console.log("test>>>", test);

return (
    <div>
        <h2>Hello</h2>
    </div>
)
  }

Following below is my output: enter image description here

Here in above output i tried to keep two state values of data and districts in a single state test but when the code is run i cannot get update value with previous value when i used spread operator to preserve previous value.Still prevoius value is not preserved,how can i solve the issue?Please help.

Upvotes: 1

Views: 5287

Answers (4)

Olga
Olga

Reputation: 217

Promise.all() is a better option for handling multiple requests that do not depend on each other.

Consider having loading set to false only when both requests are finished.

Also, the state can be simplified like this:

export default function Testmap() {
  const [isLoading, setIsloading] = useState(false);
  const [test, setTest] = useState({
    data: [],
    districts: [],
  });

  useEffect(() => {
    setIsloading(true);

    Promise.all([
      Axios.get("https://covid19wst.yilab.org.np/api/v1/form"),
      Axios.get("https://bipad.gov.np/api/v1/district/"),
    ])
      .then((results) => {
        setIsloading(false);
        setTest({
          data: results[0].data,
          districts: results[1].data.results
        });
      })
      .catch((err) => {
        setIsloading(false);
        console.log(err);
      });
  }, []);

  return (
    <div>
      <h2>Hello</h2>
    </div>
  );
}

Upvotes: 2

Rene Arteaga
Rene Arteaga

Reputation: 354

I think you can make the both http request asycn so, then you can change the variable test state once, like this:

//fetching data from api 
const fetchDataFromApi = async () => {
    let dataResponse = []
    await Axios.get('https://covid19wst.yilab.org.np/api/v1/form')
        
        .then(res => {
            setData(res.data)
            dataResponse = res.data
            setIsloading(false)

        })
        .catch(err => {
            console.log(err);
        })
    let districtResponse = []
    await Axios.get('https://bipad.gov.np/api/v1/district/')
        .then(res => {
            setDistrict(res.data.results)
            districtResponse = res.data.results
            setIsloading(false)

        })
        .catch(err => {
            console.log(err);
        })

       setTest([...test, ...dataResponse, ...districtResponse])
    }

Upvotes: 0

From Axios documentation "Performing multiple concurrent requests"

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

Promise.all([getUserAccount(), getUserPermissions()])
  .then(function (results) {
    const acct = results[0];
    const perm = results[1];
  });

Upvotes: 0

lavor
lavor

Reputation: 1877

I suggest to do it in 2 useEffect hooks:

  1. the first one will run once and will fetch data into your districts and data states.
  2. the second one will have districts and data in dependency array, so will run each time whenever data or districts changes.
import React, {useState, useEffect} from 'react';
import Axios from 'axios';

export default function Testmap() {
    const [data, setData] = useState([]);//fetched data
    const [isLoading, setIsloading] = useState(true);
    const [districts, setDistricts] = useState([]);
    const [test, setTest] = useState({
        data: [],
        districts: []
    });

    useEffect(() => {
        //fetching data from api
        Axios.get('https://covid19wst.yilab.org.np/api/v1/form')
            .then(res => {
                setData(res.data);
                setIsloading(false);
            })
            .catch(err => {
                console.log(err);
            });
        Axios.get('https://bipad.gov.np/api/v1/district/')
            .then(res => {
                setDistricts(res.data.results);
                setIsloading(false);
            })
            .catch(err => {
                console.log(err);
            });

    }, []);

    useEffect(() => {
        setTest({...test, data, districts});
    }, [data, districts]);

    return (
        <div>
            <h2>Hello</h2>
        </div>
    );
}

Upvotes: 0

Related Questions