I want to render the list of key items from API response
I get data in a const and can render the specific value like this
const cartRequest = async () => {
const res = await fetch('MYAPI', {
method: 'GET',
body: JSON.stringify()
})
const data = await res.json()
setKey(data.data)
}
<div>
{Array.from(key).map((el) => {
return (
<li>{el.app_name}</li>
)
})}
</div>
but I want to render the list of highlight keys as you see in the image, can anyone give a code example?
Related
I want to make a list of user details by filling the form with name, email, designation, phone & image input field, I've saved the form data in an object and sent the form data to it's parent using props addedUser(userData);, I'm using this addedUser prop in the parent component to send the data to the firebase and then use the same fetched data to make a list of users in array.
I've made loadedData empty array simply wanna push the data into it but the responseData.json() doesn't give me anything, the data is being saved to firebase perfectly but I'm facing problems using it.
Please check the code here and also the <Users /> component code where I'm trying to make the list:
Parent:-
function App() {
const [userData, setUserData] = useState([]);
const fetchData = useCallback(async () => {
try {
const responseData = await fetch(
"https://react-users-db-default-rtdb.asia-southeast1.firebasedatabase.app/users.json"
);
const data = responseData.json();
console.log(data);
const loadedData = [];
for (const key in data) {
loadedData.push({
key: key,
userName: data[key].userName,
userEmail: data[key].userEmail,
userDesignation: data[key].userDesignation,
usePhone: data[key].usePhone,
userImage: data[key].userImage,
});
}
console.log(loadedData);
setUserData(loadedData);
} catch (err) {
console.log(err);
}
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
async function recieveUserData(users) {
const responseData = await fetch(
"https://react-users-db-default-rtdb.asia-southeast1.firebasedatabase.app/users.json",
{
method: "POST",
body: JSON.stringify(users),
headers: {
"Content-Type": "application/json",
},
}
);
const data = await responseData.json();
console.log(data);
}
return (
<main>
<div className="form__wrap">
<AddUserForm addedUser={recieveUserData} />
</div>
<div className="user__wrap">
{userData.length > 0 ? (
<Users newUser={userData} />
) : (
<p>No user found</p>
)}
</div>
</main>
);
}
Users Component:
export default function Users({ newUser }) {
console.log(newUser);
return (
<div className="usercard__wrap">
{newUser.map((el, i) => {
return (
<UserCard
key={i}
name={el.userName}
email={el.userEmail}
designation={el.userDesignation}
phone={el.userPhone}
image={el.userImage}
/>
);
})}
</div>
);
}
Data is going to firebase:-
But responseData.json() is giving me this, I can't see my user object to access:-
In your fetchData function you need to await responseData.json().
const data = await responseData.json();
I'm very new to react. I have made a successful get request with axios and now I want to loop through the res.data and display it.
My request looks as followed:
const [post, setPost] = React.useState(null)
React.useEffect(() => {
axios({
method: 'get',
url: 'http://localhost:8080/api/tests',
headers: headers
}).then((res) => {
setPost(res.data);
console.log(res.data)
})
.catch((err) => { console.log(err) })
}, []);
Now inside my return I want to loop through every Object in the res.data array and display the name. I tried by adding a javascript forloop with curly brackets but it didn't worked.
for (var i = 0; i < post.length; i++) {
<p>{i.name}</<p>
}
Can someone help me how to get every object and render it in the return function?
You need to return something from your loop so you should use map() check the following link https://reactjs.org/docs/lists-and-keys.html. So your code should be something like the following:
Say you have the following component:
const Component = () => {
// Initialize the data with the datatype in this case it would be an empty array
// otherwise you will have to check if the array exists before looping
const [post, setPost] = React.useState([])
React.useEffect(() => {
axios({
method: 'get',
url: 'http://localhost:8080/api/tests',
headers: headers
}).then((res) => {
setPost(res.data);
console.log(res.data)
})
.catch((err) => { console.log(err) })
}, []);
return (
<div className="App">
{post.map(i => <p>{i.name}</p>)}
</div>
);
}
Now you should add a unique key to each of the items returned in a list. Not sure what your data looks like so if there is a unique identifier in each of them you should add this as the key to the item that is returned. So something like {post.map(i => <p key={i.name}>{i.name}</p>)}. But if the name value will have duplicates you would want to use a different unique identifier.
You want to use the .map() method. This allows you to create an array of jsx elements and then return that array in the component.
const Component = () => {
// Initialize the data with the datatype in this case it would be an empty array
// otherwise you will have to check if the array exists before looping
const [post, setPost] = React.useState([])
React.useEffect(() => {
axios({
method: 'get',
url: 'http://localhost:8080/api/tests',
headers: headers
}).then((res) => {
setPost(res.data);
console.log(res.data)
})
.catch((err) => { console.log(err) })
}, []);
const names = post.map(({name}, index) => <p key={index}>{name}</p>
// It's important when using .map to create jsx elements from an array,
// that you include a key prop that is unique. The index of each element
// works great in most cases
return (
<div className="App">
// React knows to spread out an array of JSX elements.
{names}
</div>
);
}
I am trying to get suggestions on a search field anytime the input field changes. However i keep running into various errors. this is what i've got so far.
export default function AutoComplete() {
const [info, setInfo] = useState([{'username': 'add a search word'},])
const [search, setSearch] = useState()
const handleChange = (e) => {
setSearch(e.target.value)
}
useEffect(() => {
const findItem = async (searchString) => {
const response = await fetch('http://localhost:8000/' + searchString, {
method: 'GET',
headers:{
'content-type': 'application/json',
},
})
let data = await response.json()
data = JSON.stringify(data)
return data
}
if (search){
var newdata = findItem(search)
setInfo(newdata)
}
else {
setInfo([{'username': 'add a search word'}])
}
}, [search])
return(
<div>
<input onChange={(e) => handleChange(e)}></input>
{info.map((suggestion) => {
return (
<div>
{suggestion.username}
</div>
)
})}
</div>)
}
The error i am running into at the moment is 'info.map is not a function' when i try to type in the input field. I decided to do my own implementation after i spent a lot of time running into this same error when i was using the material ui implementation https://mui.com/components/autocomplete/. in their implementation, they have a variable storing the data rather than calling an api and it works well. I can see that my data is being retrieved as it pops on on console.log at the end of the findItem function. Please help!
It seems that your findItem function is returning a JSON string:
data = JSON.stringify(data)
return data
Which is then set directly to the info variable:
setInfo(newdata)
This means that "info" will contain a JSON string rather than an array of JSON objects. Map doesn't work on JSON strings.
For your code to work you need to pass "setInfo" an array of objects; eg:
[
{username: "John"},
{username: "Amy"},
{username: "Peter"}
]
On form submit, a new event is added in the Database and the details of this new event are returned back via JSON. I want to concatenate this new JSON in the 'events' data so that the 'events' data gets updated automatically. But it is not working. Here is my code. Please see the line commented as //Here. It is where I am trying to update the event state variable but it is not getting updated.
import React, { useState,useEffect } from 'react';
async function getAllEvents() {
return fetch('http://localhost:8080/get-all-events/', {
method: 'GET',
//body: JSON.stringify(credentials)
})
.then(
data => data.json()
)
}
export default function Dashboard() {
const [events, setEvents ] = useState({});
const [eventName, setEventName] = useState();
useEffect(() => {
getEventsWithFetch();
}, []);
const getEventsWithFetch = async () => {
const response = await fetch("http://localhost:8080/get-all-events/");
const jsonData = await response.json();
setEvents(jsonData);
};
const addEvent = async (name) => {
const response = await fetch("http://localhost:8080/create-event/",
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"title": name,
"day": "1",
"month": "2"
})
}
).then((response) => response.json())
.then((json) => {
events.push(json);
var events_array = events;
setEvents(events_array); //Here
})
};
const handleSubmit = async e => {
e.preventDefault();
var data = new FormData(e.target)
}
return(
<div>
<p>EVENTS DASHBOARD</p>
{JSON.stringify(events)}
<form onSubmit={handleSubmit}>
<label>
<p><b>Event Name</b></p>
<input type="text" name="event_name" onChange={e => setEventName(e.target.value)} />
</label>
<div>
<button type="submit">Submit</button>
</div>
</form>
</div>
);
}
You're modifying the read-only state events, instead of using setEvents, which is already a mistake.
Furthermore, the diff-check React does is by reference for objects, so you have to clone events, instead of setting the state to itself:
setEvents([...events, json]); // Using spread to clone the array and add a new element in the end
Otherwise, React sees the same reference being set and ignores it.
I'm creating a movie search React App using axios and the TMDb API. I want to make an axios.get call to search for a movie based on query, then map over the response, and pass the movie.id for each movie into a 2nd axios call to get more details for each movie.
I have tried many approaches, but I'm confused about how I need to return the values, or if I need to use async/await at some point in the code to wait for responses. I don't really know the best way to go about this - there's got to be a simple way to do it in sequence, but the asynchronous nature of the problem makes this difficult for me.
I thought it would be simpler to make my first axios call inside my search function, and then write a second function getDetails(id) that takes a movie id and makes an axios call with it.
Ideally, if I call the getDetails function in a map, get a response, append that response to my movies array, I could easily have an array of movies with appended details to each individual movie. I could then store the entire array in state, and use a single piece of state to manage all my movie data. I know that this process is not synchronous and that axios is promise based, but is there a way to go about this sequentially or am I approaching it all wrong? I know that .push() is not working in this situation, but I have tried other methods and they have always returned undefined, a promise, or an unintended result.
const search = query => {
axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
)
.then(response => {
response.data.results.map(movie => {
const details = getDetails(movie.id);
return movie.push(details);
});
});
};
const getDetails = id => {
axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
.then(response => {
return response.data;
});
};
EDIT 1: I've played with the answer by Abanoub Istfanous, and it seemed to return undefined with the added dispatch to update my state. I tweaked it more and the second set of code marked WORKING seems to be displaying some search results, but I cannot render any of the appended data from getDetails to the screen, as they are showing undefined. Am I still doing something incorrectly?
NOT WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: data
});
return data;
};
// getDetails is unchanged...
WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data;
};
// getDetails is unchanged...
I recommend to use Promise
/*
*#return data
*/
const getDetails = async (id) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
return response.data
};
then
const search = async (query) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
}))
return data
};
The reason why it returns undefined is because Promise.all() will be executed asynchronously on the job queue and will only return the result after all Javascript gets executed and the call stack gets empty. So a simple solution to your code will be placing an await before Promise.all().
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = await Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data; //No need to return data since you are dispatching it to redux store
};
You can read more about the asynchronous nature of JS on browsers here:
https://medium.com/#Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd