DWA
DWA

Reputation: 530

Get one specific value from JSON Response in Functional React Component and set it as a Select option

I am pretty new to React and I have a Select Box that I want to populate with data from an API. The API request passes an ID for that specific user and the API returns the corresponding address to that user. I need to set the ID dynamically later on, but that´s not the problem that I am currently facing; The JSON Response is fine, it is manageable to parse through the JSON Object and to log all the Key-Value-pairs to the console; however, I am having troubles when trying to set one specific key-value pair - the one that contains the address of the user - as Option in the Select Box. The Function that I have written maps through all the data and returns just one specific key-value pair, but it keeps iterating through the JSON object and hence freezes the whole application; the returned address should be set as default option in the Select Box, the variable is called "formattedaddress".

There are definitely better ways to do that, but I don´t know how, so any hints or help would be very much appreciated, thanks in advance!

The code is the following:

import React, {Component, useContext, useEffect, useRef, useState} from 'react';
import "./formstyles.css";

//i18n
import {withNamespaces} from 'react-i18next';

//Import Breadcrumb

import { withRouter } from "react-router-dom";
import classnames from "classnames";
import EmployeesList from "../../pages/Employees/employees-list";
import EmployeeIdComponent from "./EmployeeId";

import EmployeeId from "./EmployeeId";


const SelectComponent = (props) => {


    const [loading, setLoading] = React.useState(true);
    const [error, setError] = React.useState('');
    const [data, setData] = React.useState([]);
    const [mappedArr, setMappedArr] = React.useState([]);
    const [formattedaddress, setAddress] = useState([])

// The following function returns the needed data

    let usersWithName = Object.keys(data).map(function(key) {
        JSON.stringify(data);
        let newArr = Object.keys(data);
        let mappedArr = newArr.map(function (i) {
            return [i, data[i]];
        })
        let formattedaddress = mappedArr[18];
        return formattedaddress
    });

//This effect sets the whole function as the option value

    useEffect(() => {
        setAddress(

        usersWithName
        );
    });

//The following effect fetches the data with the ID of the user and returns //the whole object

    useEffect(() => {
        setLoading(true);
        fetch('http://tpservice:8888/api/v1/address/d472faec-4316-4040-a2cb-63cb99b5bed1')
            .then((response) => response.json())
            .then((data) => {
                setLoading(false);
                setData(data);
            })

            .catch((e) => {
                setLoading(false);
                setError('fetch failed');
            });
    }, []);

    if (loading) {
        return <p>loading..</p>;
    }

    if (error !== '') {
        return <p>ERROR: {error}</p>;
    }

    return (
        <React.Fragment>
           <div className="clearfix">
                <div className="float-left">
                    <div className="input-group input-group-sm">
                        <div className="input-group-append">
                            <label className="input-group-text">Adresse</label>
                        </div>
                        <select className="custom-select custom-select-sm">
                            <option value="1">{formattedaddress}</option>
                            <option value="2">Adresse 2</option>
                            <option value="3">Adresse 3</option>
                            <option value="4">Adresse 4</option>
                        </select>
                    </div>
                </div>
            </div>
        </React.Fragment>
    );



}
export default withRouter(withNamespaces()(SelectComponent));;

Upvotes: 0

Views: 2656

Answers (1)

P.Zdravkov
P.Zdravkov

Reputation: 141

First thing, I do not see a dependency array for the useEffect??? where you call the setAddress, usersWithName - primary suspect of the behaviour you get.

Second thing I would advise exporting the request method in a custom hook rather than useEffect which you can use in your component e.g. something like const {data, loading, error} = useRequest(). It keeps your component free of gibberish and the hook is reusable.

Third, I believe what you want to do is mutate the response object with this method usersWithName, I would again implement it as a separate helper function and call it either in the hook (if not reusable) or just when you want to access the mutated values. Or you can use a useMemo which will store your mapped array and will recalculate values everytime the response changes.

Follow up:

hooks.js

const useReqest = ({ requestUrl }) = {
  const [data, setData] = useState();
  const [loading, setLoading] = useState();
  const [error, setError] = useState();

  useEffect(() => {
     fetch(...)
     .then((response) => setData(yourMutationFunction(JSON.parse(response))))
     .catch((e) => setError(e))
  }, [requestUrl])

  return {data, loading, error};
}

You can use it in component like:

// Note this hook is execited everytime requestUrl changes or is initialised
const { data, loading, error } = useRequest({requestUrl: 'someUrl'})

Try to improve this hook and work out the third part!

Upvotes: 1

Related Questions