0

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));;

1 Answer 1

1

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!

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

2 Comments

thanks a lot for your input, I really appreciate that - could you detail the second and the third part of your answer in some Pseudo code or an example on how to exactly do that? Thanks
here is some info on hooks - reactjs.org/docs/hooks-intro.html after you are familiar with them you can start writing your own ones! But you must first understand what exactly are hooks and how to use them! Better for you to try and understand it rather than me giving you the code!

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.