Store api response to an array using react useState - reactjs

I am new to react hooks. I am trying to cast API response into an array using react useState hook. It's giving me empty with the below approach
const [post, setPostArray] = useState([]);
useEffect(() => {
const postparams = { userList: result };
axios
.get(environment._urlPosts, { headers, params: postparams })
.then(posts => {
// storing response data in array
setPostArray(posts.data.post);
console.log(post);
})
.catch(err => {});
}, []);
Then I used the below approach and I was able to see data is printing in the console log
axios.get(environment._urlPosts, { headers, params: postparams }).then(posts => {
// storing response data in array
for (let obj of posts.data.post) {
post.push(obj)
}
setPostArray(post)
console.log(post)
But when I try to iterate this post array in my JSX, it's giving me empty array.
</div>
{/* array length */}
{post.length}
{post.map(post =>
<div className="card">
<Post username={post.username} fullname={post.fullname} postedTime={post.postedTime} postContent='Hi' tweeterLike={post.tweeterLike} />
</div>
)}
Can you please help me to resolve this?

Here is a minimal Example of what you are trying to achieve.
This is the working code:
import React, {useEffect, useState} from "react";
import "./styles.css";
export default function App() {
const [post, setPostArray] = useState([])
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
console.log(json);
setPostArray([json]);
})
// setPostArray([{name: 'a'}, {name: 'b'},{name: 'c'}])
},[])
console.log(post)
return (
<div className="App">
{
post.map(item => <div>{item.title} </div>)
}
</div>
);
}
Here is the link to the example in codeSandBox: https://codesandbox.io/s/jovial-snow-773kp

Related

Dynamically setting the state is not working in react

I am trying to set an array dynamically and render it using useState hook. But it seems the array is not setting. below is my code:
import React, { useState, useEffect } from "react";
export default ({ item }) => {
const [attachments, setAttachments] = useState([]);
const setAttachmentValues = function(response){
setAttachments(response.data);
}
const fetchMedia = async ()=> {
setAttachments([]);
await apiCall().then((response) => {
setAttachmentValues(response);
});
}
useEffect(() => {
fetchMedia();
}, []);
return (
<>
<div className="w-full">
{(attachments.map((ele) => {
<div>{ele}</div>
)}
</>
)
}
apiCall() will return an array of objects.
setState in this way is working well in some cases. What is the actual issue here?
This way you can render data
import React, { useState, useEffect } from 'react';
export default ({ item }) => {
const [attachments, setAttachments] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((response) => {
setAttachments(response);
console.log(response);
});
}, []);
return (
<>
<div>
{attachments.map(item => <div key={item.username}> {item.username} </div> )}
</div>
</>
);
};

Why doesn't the axios response get saved in useState variable

I've built a random photo displaying feature in react.
the console says that the response is valid and it works,
but the page breaks when I return data.
Where is the issue?
Thanks in advance!
import React from 'react'
import { useEffect, useState } from 'react'
import axios from 'axios'
function RandomPhoto() {
const url = `https://api.unsplash.com/photos/random/?client_id=${process.env.REACT_APP_UNSPLASH_KEY}`
const [data, setData] = useState()
const getPhoto = () => {
axios.get(url)
.then(response => {
setData(response.data)
console.log(response.data) // <------- works
})
.catch(error => {
console.log(error)
})
}
useEffect(() => {
getPhoto()
},[])
console.log("XX" + data) // <---------- doesn't work, and following return() neither
return (
<div>
<img href={data.urls.regular} alt={data.alt_description}/>
<p>Photo by {data.username} {data.name} from {data.location} - found on unsplash</p>
</div>
)
}
export default RandomPhoto
I modified your code a bit, and it's working. I made it as an async function and changed the path of JSON object keys.
Please note the location data sometimes returns as null. So you have to render it conditionally.
import React from 'react';
import { useEffect, useState } from 'react';
import axios from 'axios';
const RandomPhoto = () => {
const url = `https://api.unsplash.com/photos/random/?client_id=${process.env.REACT_APP_UNSPLASH_KEY}`;
const [imageData, setImageData] = useState('');
const getPhoto = async () => {
await axios
.get(url)
.then((response) => {
setImageData(response.data);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
getPhoto();
}, []);
return (
<div>
<p>Hello</p>
<img src={imageData.urls?.regular} />
<p>
Photo by {imageData?.user?.username} {imageData?.user?.name} from{' '}
{imageData?.location?.country} - found on unsplash
</p>
</div>
);
};
export default RandomPhoto;

React fetch api data not being displayed

I have a simple fetch request that runs only on the first render. When I update the state with the data and try to map through it nothing is shown. For reference the data I am given back is just one entry. Using .map it should for each entry ( which is 1) display a bullet but nothing is shown.
{quote: "I'm the new Moses"}
import logo from './logo.svg';
import {useState,useEffect} from 'react';
import './App.css';
function App() {
const [users, setUsers] = useState([])
const fetchData = () => {
fetch("https://api.kanye.rest/")
.then(response => {
return response.json()
})
.then(data => {
console.log(data)
setUsers(data)
})
}
useEffect(() => {
fetchData()
}, [])
return (
<div className="App">
<body className='App'>
<div>
{users.length > 0 && (
<ul>
{users.map(user => (
<li>{user.quote}</li>
))}
</ul>
)}
</div>
</body>
</div>
);
}
export default App;
The response value {quote: "I'm the new Moses"} is an object, not an array. It can't be mapped.
Place the response value in an array when saving.
const fetchData = () => {
fetch("https://api.kanye.rest/")
.then(response => {
return response.json();
})
.then(data => {
console.log(data);
setUsers([data]);
});
};
The result you got isn't an array, it's an object. It can't be mapped. However, you can achieve your expected behaviour in many ways. One of them is just put data into an array while setting user.
setUsers([data])

How to render the sorted array of objects using UseMemo ReactHooks

I'm trying to render the sorted array of objects using ReactHooks i have used useMemo for the same and redux as well. Could someone suggest me the best practies for it. Any suggestions on what am i doing wrong here?
I have put the post.js below as well.
I'm trying to render the sorted array of objects using ReactHooks i have used useMemo for the same and redux as well. Could someone suggest me the best practies for it. Any suggestions on what am i doing wrong here?
Thanks
HomePage.js
import React, { useState, useEffect, useMemo } from "react";
import Post from "../../Components/Post/Post";
import "./HomePage.css";
import axios from "axios";
const HomePage = () => {
const [posts, setPosts] = useState("");
let config = { Authorization: "................" };
const url = ".........................";
useEffect(() => {
AllPosts();
}, []);
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
console.log(response);
})
.catch((error) => console.error(`Error: ${error}`));
};
const newPostsByTitle = useMemo(() => {
allPosts.sort((a, b) => a.title.localeCompare(b.title)), [posts];
});
return (
<div className="home">
<div className="select">
<select
name="slct"
id="slct"
onChange={(e) => newPostsByTitle(e.target.value)}
></select>
</div>
<Post className="Posts" posts={posts} key={posts.title} />
</div>
);
};
export default HomePage;
Post.js
import React from "react";
import "./Post.css";
import { Fragment } from "react";
const Post = (props) => {
const displayPosts = (props) => {
const { posts } = props;
if (posts.length > 0) {
return posts.map((post) => {
return (
<Fragment>
<div className="Post" key={post.title}>
<img
src={post.urlToImage}
alt="covid"
width="100%"
className="img"
/>
<h5 className="title"> {post.title}</h5>
<p className="author"> {post.author}</p>
<p className="description"> {post.description}</p>
</div>
</Fragment>
);
});
}
};
return <div className="Posts">{displayPosts(props)}</div>;
};
export default Post;
You have a incorrect understanding of what the axios call dos I think.
This is just a function that on trigger will download the data, but you need to store it somewhere (e.g. posts) and use these posts instead of the api call:
const [posts, setPosts] = useState([]); // Use an empty array as defualt so it does work without data before the call
...
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
setPosts(allPosts) ?? You need to save the posts somewhere, since allPosts is not accessible outside of this function. Sicne you already have a useState, save them there
console.log(response);
})
.catch((error) => console.error(`Error: ${error}`));
};
const newPostsByTitle = useMemo(() => {
return posts.sort((a, b) => a.title.localeCompare(b.title)), [posts]; // Using {} requeores the return keyword, if you omit the {} you dont need the return statement
}); // Now access the posts saved in state to sort them
Also the key in <Post className="Posts" posts={posts} key={posts.title} /> does not work, since posts is an array not an object. So remove it.

How can I add sorting using Redux?

How can I add sorting for API returning a JSON array? I'm new to Redux. I have installed the redux. Could someone tell me what's the best method to follow?
Thanks for your help.
import React, { useState, useEffect } from "react";
import Post from "../../Components/Post/Post";
import axios from "axios";
const HomePage = () => {
const [posts, setPosts] = useState("");
let config = { Authorization: "............." };
const url = "..........................";
useEffect(() => {
AllPosts();
}, []);
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
console.log(response);
setPosts(allPosts);
})
.catch((error) => console.error(`Error: ${error}`));
};
return (
<div>
<Post className="Posts" posts={posts} />
</div>
);
};
export default HomePage;
You don't have redux here. Do you need it?
If you want to sort result and save sorted results to state:
...
.then((response) => {
const allPosts = response.data.articles;
// sort the result here
const sortedPosts = allPosts.sort((a,b) =>
// comparer
);
setPosts(sortedPosts);
})
...

Resources