Matching post author to post in React from state - javascript

I am learning React and I have successfully mapped the post titles to a div on the page. I also need to take the "userid" from the posts and get the user's name from the users state and add it to a on the div.
I can send the userid to a function which is set to return the corresponding user but it does not show up on the page. I would appreciate a review of my code to see where I am going wrong. I can log out to the console the right user but it doesn't show up on the HTML. The second in the section is the one that is not populating I would need to do that on comments as well later on so for now I just assigned a static innerHTML for that. here is my code that I have. Thanks in advance.
export default function Posts(name) {
const [posts, setPosts] = useState([]);
const [comments, setComments] = useState([]);
const [users, setUsers] = useState([])
// get Posts
useEffect(() => {
getPosts()
.then(items => {
setPosts(items)
})
// Get all Users
getUsers()
.then(users => {
setUsers(users)
})
// Get all comments
getComments()
.then(comments =>{
setComments(comments)
})
}, [])
// get individual user by userId
const getPostAuthor = (userid)=> {
users.filter((item) =>{
if ( item.id === userid){
console.log(item.name)
return item.name
}
})
}
return ( <PostsSection> {
posts.map(item => <Post><PostTitle key ={ item.title }> { item.title } </PostTitle><PostBody key={item.body}>{item.body}</PostBody><PostFooter><p>comments:4</p><p>{getPostAuthor(item.userId)}</p></PostFooter></Post>)}
</PostsSection> )
}

users.filter is returning item.name, but getPostAuthor() does not return anything. You could put a return before your users.filter function but since Array.filter() returns an array and you want one user I'd expect that is not what you want. You could instead try Array.find

Related

How to filter except users which already has been liked?

I'm trying to filter all users except current user liked people. liked is an array. allUsers is an array too. I have filtered that if user is logged in, he can't see him self in date app displayed users. But filter out those users which user already liked, it's harder.. There's my code:
useEffect(() => {
async function currentUser() {
const resp = await get(`user/${localSecret}`)
setCurrent(resp.data)
}
currentUser()
}, [])
useEffect(() => {
async function fetchUsers() {
const resp = await get(`api`)
// Filter out current user from displayed users
const filter = resp.filter(user => user.secret !== localSecret)
getAllUsers(filter)
}
fetchUsers()
}, [])
useEffect(() => {
async function getAllUsers() {
const resp = await get('api')
// Here I'm trying to filter out already liked users
// current.liked is an array of users objects
const filtered = resp.filter(user => user !== current.liked)
setAllUsers(filtered)
}
getAllUsers()
}, [])
This is mongodb user liked array of objects, to make simplier to understand:
You can try to filter with the ID of current.liked like so
const filtered = resp.filter(user => !current.liked.includes(user))
setAllUsers(filtered)
if I'm getting what you want to achieve correctly this should work. you can use underscore to always verify its object properties. it's hacky but should work. you can also move this logic to a useCallback

How do I retrieve the UID's that I have placed as documents in my Firebase Cloud Firestore

I am currently using expo react-native to create a feed in which all user posts could be retrieved, I have come up with a solution to input all of the current users posts
const Posts = firebase.firestore().collection("posts").doc(user.uid).collection("userPosts");
const [users, setUsers] = useState([]);
useEffect(async () =>{
Posts
.onSnapshot(
querySnapshot => {
const users = []
querySnapshot.forEach((doc) => {
const { caption, creation, DownloadURL} = doc.data()
users.push({
id: doc.id,
caption,
creation,
DownloadURL,
})
})
setUsers(users)
}
)
}, [])
but I could not find a way to get retrieve all the UID's of all the users with posts in order for me to access all the posts, my database goes as follows:
posts(base collection with UID's of users)->userPosts( with UIDS of each post and fields for posts )
For reference I have also tried using the same format but to no avail as I tried to pass the values and it led to 'undefined', closest I have gone is get this on the console log:
The code for the above is here:
const AllUids = firebase.firestore().collection("posts");
const [uids, setUids] = useState([]);
useEffect(async () =>{
AllUids
.onSnapshot(
querySnapshot => {
const uids = []
querySnapshot.forEach((doc) => {
const {id} = doc.data()
uids.push({
id: doc.id,
id
})
})
setUids(uids)
}
)
}, [])
console.log(uids)
Both loading data from Firestore and setting modifying the state in a React app are asynchronous operations, so by the time your console.log(uids) runs neither of those will have completed yet.
The easiest way to log the uid value, is to use another effect that depends on that state variable:
useEffect(() => {
console.log(uids);
}, [uids]);
This has been coming up repeatedly in the past days, but I'm not sure why folks are suddenly bumping into this more than before.

How to display all data

Hello I need help with showing all of a certain piece of data. my code is below
const [server, setServer] = useState()
const getServer = useCallback(async () => {
// const id = what do I do here??
const unsubscribe = firebase.db.collection("servers").doc('S7FlCYEvxIVDs7MRymnK').onSnapshot(snapshot => {
setServer(snapshot.data())
})
return unsubscribe
},[props.server])
useEffect(() => {
getServer()
}, [props])
console.log(server)
you can see I want to replace the hard coded doc info with an id variable, so in my project I can show multiple servers instead of a hard coded one I choose.

Reset React state before a render

I'm building a web application that consumes TMDB Api. I have the following code that fetch all information about a TV Show
export const useShowInfoFetch = ({showId}) => {
const [data, setData] = useState({})
const [loading, setLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchShowInfo = useCallback(() => {
setLoading(true)
try {
axios.get(getShowInfo(showId))
.then(response => {
setData(response.data)
})
} catch (error) {
_setError(true)
} finally {
setLoading(false)
}
}, [showId])
useEffect(() => {
fetchShowInfo()
}, [fetchShowInfo])
return [data, loading, _error]
}
All the information fetched is displayed in page, that also has Links with react-router-dom. Those links goes to another tv show page.
The problem is that when I'm in a page with a tv show that has X amount of seasons and I click a tv show with less seasons, the seasons from the page I was are persisting for a little bit of time. So, when I fetch the information for each season I got a 404 in the page that has less seasons.
Here is a screenshot of the error
The orange circle is what it's displayed since I click the tv show with less seasons.
As you can see, the seasons from the previous page are persisting for a little time, and because The Alienist has only 2 seasons (not 9) I get the 404. You can also note that latter, the correct amount of seasons are displayed.
I've tried to add a cleanup method in the useEffect hook. Something like this:
useEffect(() => {
fetchShowInfo()
return function cleanup() {
setData({})
}
}, [fetchShowInfo])
But this did not work.
I know that I can handle that with a catch after the then Axios promise, but I want to figure out why this is happening and fix the issue with a good solution instead of avoiding it.
Any help is welcomed and I can share the repository with all the code if needed.
EDIT:
To display the similar movies I use another custom hook
export const useSimilarFetch = (elementType, elementId) => {
const [similarElements, setSimilarElements] = useState({elements: []})
const [similarLoading, setSimilarLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchSimilarElements = useCallback(async (endpoint) => {
console.log(">>> fetching similar elements <<<")
setSimilarLoading(true)
try {
await axios.get(endpoint)
.then(response => {
setSimilarElements(() => ({
elements: [...response.data.results],
currentPage: response.data.page,
totalPages: response.data.total_pages
}))
})
} catch (error) {
_setError(true)
} finally {
setSimilarLoading(false)
}
}, [])
useEffect(() => {
fetchSimilarElements(getSimilar(elementType, elementId));
}, [fetchSimilarElements, elementType, elementId])
return [{similarElements, similarLoading, _error}, fetchSimilarElements]
}
Then, in my ShowInfoComponent I call all the needed hooks like this:
const {showId} = useParams()
const [data, loading, _error] = useShowInfoFetch({showId})
const [{similarElements, similarLoading}] = useSimilarFetch("tv", showId)
Thanks.
By the time showId changes, data has to wait one additional render cycle, so showId is already used even though data has not yet been fetched. The UI relies on both showId and data, yet data depends on showId. One way to solve this could be having your UI to rely on data alone. What about the id? Add it to data for example. We merely want to avoid the desynchronization.
Something like this:
export const useShowInfoFetch = ({showId}) => {
const [data, setData] = useState({})
const [loading, setLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchShowInfo = useCallback(() => {
setLoading(true)
try {
axios.get(getShowInfo(showId))
.then(response => {
setData({ id: showId, info: response.data})
})
} catch (error) {
_setError(true)
} finally {
setLoading(false)
}
}, [showId])
useEffect(() => {
fetchShowInfo()
}, [fetchShowInfo])
return [data, loading, _error]
}
Then use data.id to build your links.
If response.data already contains the id, then even better, use that.
That's just an example, of course but hopefully you get the idea.
I might be wrong but I believe you are not watching the correct value on the useEffect. You should be watching showId and not the function fetchShowInfo. That is:
useEffect(() => {
fetchShowInfo()
}, [showId]) --> HERE
And as you are memoized the callback, if you are watching the wrong variable then you will get back the 'last answered'.

Updating react state when receiving an array of object

I am using an axios.get to make a call to my MongoDB. My response from the DB is an array of objects containing all the data from the database. I am only trying to save the username of each user to state. I am trying to set the response (res.data.username) to my state however when i log my state I am getting an empty array back. PS: There was no way to copy my response so i added an image of the response for reference, let me know if there's a better way to show the response
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/users')
.then(res => {
if (res.data.length > 0) {
console.log(res.data)
setUsers(user => [...user, res.data.username]);
}
})
}, [])
Since users is an array, Pass the array to setUsers.
Use destructuring to for readability and simplification.
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("http://localhost:5000/users").then((res) => {
if (res.data.length > 0) {
console.log(res.data);
setUsers(res.data.map(({ username }) => username));
}
});
}, []);
res.data is an array.
to just set username from response you can try
setUsers(user => [...user, res.data.map(response => response.username)]);
setUsers(res.data.map(({ username }) => username));

Categories

Resources