Dynamically setting the state is not working in react - reactjs

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

Related

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;

cant access an obj in multidimensional array

import axios from "axios";
import { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
let [data, setdata] = useState([]);
const update = async () => {
try {
await axios
.get("https://mocki.io/v1/94d0cd81-ed46-4db6-9304-c5e119bcf334")
.then((res) => {
setdata(res.data);
console.log(data);
});
} catch (error) {
console.log(error);
}
};
useEffect(() => {
update();
}, []);
return (
<div className="App">
{data.map((e) => {
return (
<>
<h1>{e.number[0].school}</h1>
</>
);
})}
<button onClick={update}>click me</button>
</div>
);
}
can someone help me so solve this problem, please?
i am trying to display the number's obj, but i cant.
its not the real one, but i make it as similar as the real one.
any help will be appreciated.
thankyou

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.

Correct way to use useEffect() to update when data changes

The useEffect below renders, fetches data, and displays it once (using an empty array for 2nd parameter in useEffect).
I need it to rerun useEffect everytime the user changes data to the database (when user uses axios.post).
What i've tried
using [tickets], but that just causes the useEffect to run infinitly
also using [tickets.length] and [tickets, setTickets]
trying to use props as parameter but didnt find anything useful
import React, { useState, createContext, useEffect } from "react";
import axios from "axios";
export const TicketContext = createContext();
export const TicketProvider = (props) => {
console.log(props);
const [tickets, setTickets] = useState([]);
useEffect(() => {
getTickets();
console.log("1", { tickets });
}, []);
const getTickets = async () => {
const response = await axios.get("http://localhost:4000/tickets/");
setTickets(response.data);
};
return <TicketContext.Provider value={[tickets, setTickets]}>{props.children}
</TicketContext.Provider>;
};
import React from "react";
import { useState, useEffect, useContext } from "react";
import Ticket from "../Ticket";
import { TicketContext } from "../contexts/TicketContext";
import AddBacklog from "../addData/AddBacklog";
const TicketDisplay = (props) => {
const [tickets, setTickets] = useContext(TicketContext);
return (
<div className="display">
<p>Antony Blyakher</p>
<p>Number of Tickets: {tickets.length}</p>
<div className="backlog">
<h1>Backlog</h1>
{tickets.map((currentTicket, i) => (
<div className="ticketBlock">
<Ticket ticket={currentTicket} key={i} />
</div>
))}
</div>
</div>
);
const AddBacklog = (props) => {
const [tickets, setTickets] = useState("");
...
axios.post("http://localhost:4000/tickets/add", newTicket).then((res) => console.log(res.data));
setTickets((currentTickets) => [...currentTickets, { name: name, status: "backlog", id: uuid() }]);
};
You'll need to watch for tickets and return if it has data to not cause infinite loop:
useEffect(() => {
if (tickets.length) return // so, we call just once
getTickets();
console.log("1", { tickets });
}, [tickets]);
const fetchData = () => {
axios.get("http://localhost:7000/api/getData/").then((response) => {
console.log(response.data);
if (response.data.success) {
SetIsLoading(false);
}
setDataSource(response.data.data);
});
};
useEffect(() => {
fetchData();
if (fetchData.length) fetchData();
}, [fetchData]);
by this you can fetch the data in real-time as any change in data occurs.

Store api response to an array using react useState

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

Resources