export async function onGetNews(){
let data = await axios.get(`${Link}/news`, {
params: {
limit: 1
}
}).then(res => {
return (res.data)
});
return data
}
I tried a lot of solutions and I didn't find a good one. I use limit and other ... and when I use useEffect with export function it gives me an error
export function OnGetServices(){
const [service, setService] = useState([])
useEffect(() => {
setTimeout(async () => {
let data = await axios.get(`${Link}/services`, {}).then(res => {
setService(res.data)
});
}, 1000);
console.log(data);
}, []);
console.log(service);
return service;
}
Why are you doing .then() when you are using async/await? Try this:
export async function onGetNews(){
let res= await axios.get(`${Link}/news`, {
params: {
limit: 1
}
});
return res.data
}
And your react snippet can be:
export function OnGetServices(){
const [service, setService] = useState([])
useEffect(() => {
setTimeout(async () => {
let res = await axios.get(`${Link}/services`, {})
setService(res.data);
console.log(res.data);
}, 1000);
}, []);
}
And if you don't really need the setTimeout, you could change the implementation to:
export function OnGetServices(){
const [service, setService] = useState([])
useEffect(() => {
const fn = async () => {
let res = await axios.get(`${Link}/services`, {})
setService(res.data);
console.log(res.data);
}
fn();
}, []);
}
Async/await drives me crazy either. I wrote a solution, but I'm not sure if it performs good practices. Feedback appreciated.
https://codesandbox.io/s/react-boilerplate-forked-y89eb?file=/src/index.js
If it's a hook then it has to start with the "use" word. Only in a hook, or in a Component, you can use hooks such as useEffect, useState, useMemo.
export function useService(){ //notice the "use" word here
const [service, setService] = useState([])
useEffect(() => {
setTimeout(async () => {
let data = await axios.get(`${Link}/services`, {}).then(res => {
setService(res.data)
});
}, 1000);
console.log(data);
}, []);
console.log(service);
return service;
}
const SomeComponent = () => {
const service = useService();
}
Related
I'm new to react and I'm learning how to use useEffect. I encountered this warning in my react app. I tried out some solutions on SO but the warning still remains. Both fetchUser and fetchPosts trigger this warning. Can anyone enlighten me what is the problem and what does the warning mean?
App.js
useEffect(() => {
setLoading(true)
const getUser = async () => {
const userFromServer = await fetchUser()
if (userFromServer) {
setUser(userFromServer)
setLoading(false)
} else {
console.log("error")
}
}
getUser()
}, [userId])
useEffect(() => {
const getPosts = async () => {
const postsFromServer = await fetchPosts()
setPosts(postsFromServer)
}
getPosts()
}, [userId])
useEffect(() => {
const getUserList = async () => {
const userListFromServer = await fetchUserList()
setUserList(userListFromServer)
}
getUserList()
}, [])
// Fetch user
const fetchUser = async () => {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
const data = await res.json()
return data
}
// Fetch posts
const fetchPosts = async () => {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`)
const data = await res.json()
return data
}
// Fetch list of users
const fetchUserList = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users/')
const data = await res.json()
return data
}
If you are using any function or state which has been declared outside the useEffect then you need to pass it in the dependency array like this:
const someFunctionA = () => {
....
}
const someFunctionB = () => {
....
}
useEffect(() => {
....
}, [someFunctionA, someFunctionB])
You can read more about it here in case you want to know how it will be rendered: React useEffect - passing a function in the dependency array
How do I update the state data immediately when I use Axios with async and await? It seems not updating the state data immediately. Many thanks in advance and greatly appreciated. Here is the code sample:
const[dbdata,setDBData] = useState([])
useEffect(async() => {
const response = await Axios.get('http://localhost:5000/api/posts/allpost', {withCredentials:true})
setDBData(response.data)
}, [])
const GetPost = async(id) =>{
const response = await Axios.put('http://localhost:5000/api/posts/getPost',{postId:id}, {withCredentials:true})
const getData = dbdata.map(item => {
if(item._id==response._id){
return response
}
else{
return item
}
})
console.log(getData)
setDBData(getData)
}
useEffect(async () => ...) are not supported, but you can call an async function inside an effect.
Try:
useEffect(() => {
const GetPost = async(id) =>{
const response = await Axios.put('http://localhost:5000/api/posts/getPost',{postId:id}, {withCredentials:true});
const getData = dbdata.map(item => {
if(item._id==response._id){
return response;
}
else{
return item;
}
})
console.log(getData);
setDBData(getData);
}
GetPost();
}, [])
EDIT:
OR:
useEffect(() => {
GetPost();
}, []);
const GetPost = async(id) =>{
const response = await Axios.put('http://localhost:5000/api/posts/getPost',{postId:id}, {withCredentials:true});
const getData = dbdata.map(item => {
if(item._id==response._id){
return response;
}
else{
return item;
}
})
console.log(getData);
setDBData(getData);
}
in useEffect hook i used a function to send request to api for search.
function name is searchCharacters and it is outside of component.
i get error
TypeError: searchCharacters(...) is undefined when my code excuted on that point. why? how can in fix this?
error img:
function Dashboard() {
const [searchParam, setSearchParam] = useState("");
const [results, setResults] = useState([]);
const [isSearching, setIsSearching] = useState(false)
const debouncedSearchTerm = useDebounce(searchParam, 500);
useEffect( ()=> {
if(debouncedSearchTerm){
setIsSearching(true);
searchCharacters(debouncedSearchTerm).then(res => {
setIsSearching(false);
console.log("im search result", res);
setResults(res);
});
}else{
setResults([]);
}
}, [debouncedSearchTerm]);
}
function searchCharacters(search){
api.get(`client/search?q=${search}`).then(
(res) => {
return res.data;
}
).catch( e => {
console.log(e);
return [];
})
}
export default Dashboard;
searchCharacters doesn't return a Promise to chain from. Return the api.get Promise chain from searchCharacters.
function searchCharacters(search) {
return api
.get(`client/search?q=${search}`)
.then((res) => {
return res.data;
})
.catch((e) => {
console.log(e);
return [];
});
}
Or slightly more succinct
const searchCharacters = (search) =>
api
.get(`client/search?q=${search}`)
.then((res) => res.data)
.catch((e) => {
console.log(e);
return [];
});
How would one go about using the useEffect hook to replace both componentDidMount and componentWillUnmount while working with Firebase? I can't find a solution to this 'unsubscribe' function.
unsubscribe = null;
componentDidMount = async () => {
this.unsubscribe = firestore.collection('posts').onSnapshot(snapshot => {
const posts = snapshot.docs.map(...)
this.setState({ posts })
})
}
componentWillUnmount = () => {
this.unsubscribe()
}
Here's what I tried:
useEffect(() => {
async function getSnapshot() {
const unsubscribe = firestore.collection('posts').onSnapshot(snapshot => {
const posts = snapshot.docs.map(...)
setPosts(posts)
}
getSnapshot()
//return something to clear it? I don't have access to 'unsubscribe'
}, [])
You are actually pretty close with your answer. You weren't using await in your function, so there was no point in using it.
useEffect(() => {
const unsubscribe = firestore.collection('posts').onSnapshot((snapshot) => {
const posts = snapshot.docs.map(...)
setPosts(posts);
});
return () => {
unsubscribe();
};
}, []);
If you did need to use async, you can just utilize the closure to get unsubscribe out of the async function.
useEffect(() => {
let unsubscribe;
async function getSnapshot() {
unsubscribe = firestore.collection('posts').onSnapshot((snapshot) => {
const posts = snapshot.docs.map(...)
setPosts(posts);
});
}
getSnapshot();
return () => {
unsubscribe();
};
}, []);
you're probably going to run into trouble using async inside useEffect, check out https://www.npmjs.com/package/use-async-effect
useAsyncEffect( async() => {
const unsubscribe = await firestore.collection('posts').onSnapshot(snapshot => {
const posts = snapshot.docs.map(...)
setPosts(posts)
}
return () => {
console.log("unmount")
unsubscribe()
};
}, [])
EDIT: actually it seems from the docs that you don't need async at all there:
have you tried this format?
useEffect(
() => {
const unsubscribe = firebase
.firestore()
.collection('recipes')
.doc(id)
.collection('ingredients')
.onSnapshot( snapshot => { const ingredients = [] snapshot.forEach(doc => { ingredients.push(doc) }) setLoading(false) setIngredients(ingredients) }, err => { setError(err) } )
return () => unsubscribe()
},
[id]
)
GET requests canceling fine in this example:
export default function Post (props) {
const _cancelToken = axios.CancelToken.source()
useEffect(() => {
const _loadAsyncData = async () => {
await axios.get('/post'), { cancelToken: _cancelToken.token })
}
_loadAsyncData()
return () => {
_cancelToken.cancel()
}
}, [])
return ()
}
But when I need save form via POST request, my code looks like:
export default function Form (props) {
const _cancelToken = axios.CancelToken.source()
const _zz = { qq: 'QQ' }
const handleCreate = async e => {
e.preventDefault()
_zz.qq = 'ZZ'
await axios.post('/form'), {}, { cancelToken: _cancelToken.token })
}
useEffect(() => {
return () => {
console.log(_zz.qq)
_cancelToken.cancel()
}
}, [])
return ()
}
Request not cancel and my _zz.qq always 'QQ' instead 'ZZ'. It's working fine without hooks, but I like hooks and want to use hooks for new components.
I want to cancel request when componentWillUnmount.
This is because you're losing the changes between renders. During the handleCreate call the variable changes only for that render. When the useEffect is run on a subsequent render/unmounting, you're resetting _zz to { qq: 'QQ' }. In order to get around this you need to use references.
export default function Form (props) {
const cancelToken = useRef(null)
const zz = useRef({ qq: 'QQ' })
const handleCreate = async e => {
e.preventDefault()
cancelToken.current = axios.CancelToken.source()
zz.current = { qq: 'ZZ' }
await axios.post('/form'), {}, { cancelToken: cancelToken.current.token })
}
useEffect(() => {
return () => {
console.log(zz.current) //this should now be {qq : 'ZZ'}
if (cancelToken.current) {
cancelToken.current.cancel()
}
}
}, [])
return null
}