How to set value to input field in react - javascript

How to set the value to the input field in react. Data is fetching from firebase.
I was trying to fetch data from the firebase and then data is populated to the input field. But data is sometimes set to input field sometimes not.

You have to fill your data into a local state using useState. Here is the general idea. Can't go into more details without code example from your side.
For example:
const [value, setValue] = useState('')
Then in your useEffect fetching the data:
useEffect(() => {
const data = fetch('gettingdata') // replace by the way you get your data
setValue(data)
}, []}
Then in your input:
<input value={value} onChange={manageYourValueChange} />

You can use the useRef hook to avoid unnecessary rerender:
import {useRef, userEffect} from 'react'
const Test:React.FC = () => {
const inputRef = useRef(null)
userEffect(() => {
const resp = yourAsyncGetData()
inputRef.current.value = (resp)
}, [])
return <input ref={inputRef} />
}
export default Test

Related

Passing API call results to trigger render in react

I am fairly new to react and am stuck on how i pass the results of my api call to another component file to then trigger a render. Can anyone give me a simple explanation of what I need to to please?
this is my code that calls to the API and then i need the weatherDescription state to be used in and IF statement to conditionally render a local GLTF file to the canvas
import { useEffect } from "react";
import { useState } from "react";
import "dotenv";
export default function WeatherLogic() {
const [userLocation, setUserLocation] = useState("");
const [temperature, setTemp] = useState("");
const [weatherDescript, setWeatherDescript] = useState("");
const handleInput = (event) => {
setUserLocation(event.target.value);
};
const getWeather = async (userLocation) => {
const apiKey = import.meta.env.VITE_APP_API_KEY;
const res = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${userLocation}&appid=${apiKey}&units=metric`
);
const data = await res.json();
setTemp(data.main.temp);
setWeatherDescript(data.weather[0].description);
};
useEffect(() => {
getWeather(userLocation);
}, [userLocation]);
return (
<div className="formcontainerparent">
<div className="formcontainerchild">
<form className="weatherform">
<label>Location
<input
type="text"
name="name"
value={userLocation}
onChange={handleInput}
/>
</label>
</form>
<h1>{userLocation}</h1>
<h2>{temperature}°C</h2>
<h3>{weatherDescript}</h3>
</div>
</div>
);
}
One of the approaches will be to make a state for local GLTF file like:
const [file,setFile] = useState(null)
then make another useEffect hook and set this file on discription changes, i.e, add weatherDescript in it's dependency array:
useEffect(() => {
if(condition)
setFile(...datawhichyouneedtorender)
}, [weatherDescript]);
And lastly, in your jsx render the file variable in convas.

Storing list with objects in a state for future use in react

I am getting a response like this from my axios response and I want to store the same in a state to pass it further.
Please help me how I store this in a state. I am very new to react.
You can accomplish this by setting your state variable to something like this:
const Component = () => {
let [items, setItems] = useState([]);
useEffect(() => {
axios.get('https://someurl.com')
.then(data => {
setItems(data)
})
}, [])
}
In your render function, you can then access the items array normally. Hope this helps!
first import useState from react
and then do something like this with the response you are getting.
import react, {useState} from 'react'
const App = () => {
const [data,setData} = useState([])
}
And inside the function that triggers the add event
setData(res.data)
If you want to save the response in the state, first you need to create a state:
const [value, setValue] = React.useState([]);
Next, you need to use setValue to put your response in the state:
setValue(API_RESPONSE)
So React will render this change and you can print value to see what value this const has.

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

How to insert setState value into useEffect hook?

I watched a Youtube video and I made my own recipe app. I'm a beginner at React.js and I've been solving this problem for about 2 days. Seems that i cant pass the value of my state to useEffect hook. Here's an example of my code. The error says
"React Hook useEffect has a missing dependency: 'query'. Either include it or remove the dependency array" and everytime I typed in the input box it triggers the useEffect hook. Thank you and your help is very much appreciated.
const [recipes, setRecipes] = useState([]);
const [search, setSearch] = useState('');
const [query, setQuery] = useState('steak');
const updateSearch = e => {
setSearch(e.target.value);
console.log(search)
}
const getSearch = e => {
e.preventDefault();
setQuery(search);
}
useEffect(() => { // error Is from the Query variable
const GetRecipe = async () => {
const APP_ID = "3834705e";
const APP_KEY = "c23e9514f82c2440abf54b21edd4c3dc";
const res = await fetch(`https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`);
const data = await res.json();
setRecipes(data.hits);
}
GetRecipe();
},[getSearch]) //this triggers everytime I typed in the input box which is not it is supposed to
return(
<div className='recipelist'>
<form onSubmit={getSearch}>
<input type="search" onChange={updateSearch}/>
<button type='submit'>submit</button>
</form>
As the error tells you, when using a useEffect hook, that hook can receive two arguments, the first one is the handler effect and the second one is an array containing all dependencies that effect will use, so as you are using the query state into the http url, you need to pass that dependency into the array, so could be something like this.
useEffect(() => { // error Is from the Query variable
const GetRecipe = async () => {
const APP_ID = "3834705e";
const APP_KEY = "c23e9514f82c2440abf54b21edd4c3dc";
const res = await fetch(`https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`);
const data = await res.json();
setRecipes(data.hits);
}
GetRecipe();
},[getSearch, query])
so what is actually doing the array dependency, as React docs says, array dependency it's used to check if the effect should execute again based on its dependencies, so in your code everything you type something, getSearch method is re-creating again and again in memory, so it will check the last getSearch function that it took and compare it with the new ones, so it will check as equally checker like fn1 === fn2, so due to both function are exactly the same, both keeps different space in memory, so both are different objects, check this docs to understand the concept.
Here you have the react docs too

cant update context state when using hooks with a complex object to set providers value

When I call toggleFilterSidebar it should toggle the state of filterSidebarIsOpen from false to true and vice versa but onClick nothing happens, but when I pass the Provider value directly as an object it works.
Why does this work?
1).
return <FilterSidebarContext.Provider value={{
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
}}>{children}</FilterSidebarContext.Provider>;
and this doesnt
2).
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
return <FilterSidebarContext.Provider value={value}>{children}</FilterSidebarContext.Provider>;
My Code
FilterSidebar.context.js
import React, { useState } from 'react';
export const FilterSidebarContext = React.createContext({});
export const FilterSidebarProvider = ({ children }) => {
const [filterSidebarIsOpen, setFilterSidebarIsOpen] = useState(true);
const toggleFilterSidebar = () => setFilterSidebarIsOpen(!filterSidebarIsOpen);
const [filters] = useState({ regions: [] });
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
return <FilterSidebarContext.Provider value={value}>{children}</FilterSidebarContext.Provider>;
};
export const FilterSidebarConsumer = FilterSidebarContext.Consumer;
export default FilterSidebarContext;
FilterButton.js
const FilterButton = ({ className, getTotalActiveFilters }) => {
const { toggleFilterSidebar, filterSidebarIsOpen } = useContext(FilterSidebarContext);
return <Button className={cx({ [active]: filterSidebarIsOpen })} onClick={toggleFilterSidebar} />;
};
With this code:
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
you are providing useState with an initial value which is only used when the component is first mounted. It will not be possible for value to ever change since you aren't even creating a variable for the setter (e.g. const [value, setValue] = useState(...)).
I assume you are using useState here to try to avoid a new object being created with each render and thus forcing a re-render of everything dependent on the context even if it didn't change. The appropriate hook to use for this purpose is useMemo:
const value = useMemo(()=>({
toggleFilterSidebar,
filterSidebarIsOpen,
filters
})[filterSidebarIsOpen]);
I've only put filterSidebarIsOpen into the dependencies array, because with your current code it is the only one of the three that can change (toggleFilterSidebar is a state setter which won't change, filters doesn't currently have a setter so it can't change).
useState expects a function to set the value after useState initially does, so if value represents state, setValue would represent setState...
const [value, setValue] = useState(initialValue);
then use setValue to change it
onClick={() => setValue(newValue)}

Categories