react native - problem with useState, fetch value? - react-native

I want to update the 'people' field. The problem is that the previous value goes to the state, not the current one. I don't know how to make it correct.
I am getting a value from previous rendering
const [totalPeoplem, setTotalPeople] = useState(0);
const handleUpdate = async (initialItem) => {
firestore()
.collection('users')
.doc(user.uid)
.collection('city')
.doc(itemId)
.update({
people: totalPeople
}).then(() => {
console.log('Update');
});
}

You can solve it with useEffect
For example:
const [totalPeoplem, setTotalPeople] = useState(0);
useEffect(() => {
const handleUpdate = async (initialItem) => {
await firestore()
.collection('users')
.doc(user.uid)
.collection('city')
.doc(itemId)
.update({
people: totalPeoplem,
}).then(() => {
console.log('Update');
});
};
handleUpdate()
}, [totalPeoplem]);

Related

How to pass the parameter to another screen using axios?

I'm doing the verification of the phone number, and I have to pass the phone number to the other checkCode.js component.
I have seen examples that pass it navigate() as a pramas, but how can I receive it in another component.
register.js
const SignUp = ({ navigation }) => {
const [phoneNumber, setPhoneNumber] = useState('');
let register = "https://app.herokuapp.com/api/v1/auth/register"
let sendVerification = "https://app.herokuapp.com/api/v1/auth/sendVerification-otp"
const signUp = () => {
const userParams = {
phone: phoneNumber,
};
const requestOne = axios.post(register, userParams)
const requestTwo = axios.post(sendVerification, userParams)
axios
.all([requestOne, requestTwo], userParams)
.then(axios.spread((...responses) => {
navigation.navigate('CodeVerification')
}))
.catch((err) => {
console.log('the error:', err.message);
})
}
checkCode.js
export default function CodeVerification({navigation}) {
//need phoneNumber param in this component
const [code, setCode] = useState('');
const confirm = () =>{
const userParams = {
phone: "+11111111",
code:code,
};
axios
.post('https://app.herokuapp.com/api/v1/auth/sendVerification-otp', userParams)
.then((response) =>{
console.log('response', response.data);
navigation.navigate('Welcome')
})
.catch((error) => {
console.log('the error:', error.message);
});
};
How can I pass it?
This might help
register.js
const SignUp = ({ navigation }) => {
// existing code remains the same
const signUp = () => {
....
axios
.all([requestOne, requestTwo], userParams)
.then(
axios.spread((...responses) => {
// send params like this
navigation.navigate("CodeVerification", {phone: phoneNumber});
})
)
.catch((err) => {
console.log("the error:", err.message);
});
};
};
checkCode.js
export default function CodeVerification({ route, navigation }) {
// get phoneNumber from props
const {phone} = route.params; // UPDATED this line
const [code, setCode] = useState("");
....
}
You can use Context Api
Context api is commonly used for transferring data to another component.

React Native -how to clean use effect hook

I'm new to react native and currently trying to make an app with firebase v9 for practice. I'm kinda stuck with the hook issue, as it says:
[Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.]
This is the Login Component:
const LoginScreen = ( {navigation}) => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [storeKey, setStoreKey] = useState([]);
const [userName, setName] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [image, setImage] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (authUser) => {
if(authUser){
AfterLogin();
}
});
return unsubscribe;
}, []);
const signInUser = () => {
signInWithEmailAndPassword(auth, email, password)
.then(async (re) => {
//setIsSignedIn(true);
AfterLogin();
})
.catch((error) => {
console.error(error);
})
}
const AfterLogin = () => {
if(!storeKey || !userName || !image){
getData(setStoreKey, setName, setIsLoading, setImage);
}
navigation.replace('Drawer', {
storeKey: storeKey,
userName: userName,
image: image,
});
}
And this is the getData Function:
const getData = async(setStoreKey, setName, setIsLoading, setImage) => {
const auth = getAuth();
const user = auth.currentUser;
if(user !== null){
const email = user.email;
const UserInfo = await getDoc(doc(db, 'users', email));
if(UserInfo.exists()){
setStoreKey(UserInfo.data().storeKey)
setName(UserInfo.data().name);
setIsLoading(false)
setImage(UserInfo.data().postImage)
}
else{
console.log('None')
}
return
}
}
I guess the problem is happening in the useEffect in Login, but I don't know how to solve this :S
EDIT: I think the problem is from getData function. When I comment out getData function in AfterLogin, it works fine without error :S
but I don't know how it causes error.
Is it because it's async function?
Try this
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (authUser) => {
if(authUser){
AfterLogin();
}
});
return () => {
unsubscribe();
}
}, []);

React Native: No thing show on the screen after getting data from firestore

This is my code:
const [tourists, setTourists] = useState(null)
const [saved,setsave]=useState('');
const {user, logout} = useContext(AuthContext);
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const getUser = async() => {
await firestore()
.collection('users')
.doc( user.uid)
.get()
.then((documentSnapshot) => {
if( documentSnapshot.exists ) {
console.log('User Data in BookMark', documentSnapshot.data());
const list=[];
setUserData(documentSnapshot.data());
console.log('savedPosts: ',documentSnapshot.data().savedPosts);
documentSnapshot.data().savedPosts.map((object, index) => (
firestore().collection('posts').doc(object).get().then((querySnapshot) => {list.push(querySnapshot.data())})
))
setTourists(list);
if (loading) {
setLoading(false);
}
}
})
}
useEffect(() => {
getUser();
}, []);
return (
<View style={{flex: 1, marginTop: Constants.statusBarHeight}}>
{!loading ? ((tourists ||[]).map((object, index) => (...
I have checked through the console and see that firestore worked correctly, I got the data, tourists is not null, but the screen still shows nothing. Can anybody hekp me plz !!!
The issue is in this part:
const list=[];
setUserData(documentSnapshot.data());
console.log('savedPosts: ',documentSnapshot.data().savedPosts);
documentSnapshot.data().savedPosts.map((object, index) => (
firestore().collection('posts').doc(object).get().then((querySnapshot) => {list.push(querySnapshot.data())})
))
setTourists(list);
Becase you use then the setTourists(list) will always save an empty array because then finished after you already set the value. Also a map doesn't support async calls. We need to use a for loop for this.
Change your code to something like this:
const getUser = async () => {
await firestore()
.collection("users")
.doc(user.uid)
.get()
.then(async (documentSnapshot) => {
if (documentSnapshot.exists) {
console.log("User Data in BookMark", documentSnapshot.data());
const list = [];
const posts = [];
setUserData(documentSnapshot.data());
documentSnapshot.data().savedPosts.map((object, index) => {
posts.push(object);
});
for (let i = 0; i < posts.length; i++) {
const post = posts[i];
const docSnapshot = await firestore()
.collection("posts")
.doc(post)
.get();
list.push(docSnapshot.data());
}
setTourists(list);
if (loading) {
setLoading(false);
}
}
});
};

React Native hooks useState - setState array dont work

When i try to set state from API, i have response.data but setState dont work.
const [items, setItems] = useState([]);
useEffect(() => {
cargarItems();
}, [])
const cargarItems = async () => {
const res = await fetch('http://localhost:4000/api/items');
const data= await res.json();
setItems(data);
console.log(data);
console.log(items); }
Also try:
await axios
.get('http://localhost:4000/api/items')
.then((res) => {
console.log(typeof res.data);
setItems(res.data);
})
.catch((err) => {
console.log(err);
});
console.log(items);
And allways i get:
I have the response but the state is not updated.
Thanks in advance

how do I make an array in state - reactnative

I'm taking the images I uploaded to cloud storage, but the problem is the variable is not an array, so it is only storing just one url. How do I make variables with state array?
My code:
const reference = storage().ref('images');
const [imageUrl, setImageUrl] = useState();
const refer = storage().ref('images');
useEffect(() => {
try {
listFilesAndDirectories(reference).then(() => {
console.log('Finished listing');
});
refer.list().then(result => {
result.items.forEach(element => {
element.getDownloadURL().then(downloadUrl => {
setImageUrl(downloadUrl)
console.log(imageUrl)
console.log("=================")
}).catch(error =>{
alert(error)
})
})
})
} catch (error) {
alert(error);
}
}, []);
Is that what you are looking for?
const [items, setItems] = useState([]);
const handleStateChange = () => {
setItems(state => [...state, 'someNewItem']);
}
With useCallback
const handleStateChange = useCallback(function () {
setItems(state => [...state, 'someNewItem']);
}, [])