I'm writing a simple Async Storage set Item call in React Native to store my store's cart data. But the call fails. I can't find possible reason why it so as there is no mention of such in the documentation. I have added the relevant code. Please help would be appreciated.
const ProductDetailScreen = (props) => {
const {product} = props.route.params;
const getCart = async () => {
return await AsyncStorage.getItem('cart');
};
const cart = getCart();
const addToCart = async () => {
try {
await AsyncStorage.setItem('cart', [
...cart, JSON.stringify(product),
]);
} catch (e) {
console.error(`Failed to add item: {${JSON.stringify(product)}} to cart`);
}
};
return (
<>
<TouchableOpacity onPress={addToCart}>
<Button>
<Text style={styles.btnText}>Add to Cart</Text>
</Button>
</TouchableOpacity>
</>
)
};
export default ProductDetailScreen;
error log
ERROR Failed to add item: {{"id":2,"name":"Scene Stealers","description":"Corset cuts","price":250,"image":5,"colors":["#0F140D","#DD8560","#E1E0DB"],"sizes":["S","M","L"]}} to cart
You can only store/set string data in AsyncStorage while you are trying to store Array
await AsyncStorage.setItem('cart', JSON.stringify([...cart, JSON.stringify(product)]))
Related
I am making an api call to the steam review api with this link: "api link"
I have used another link with my code and was able to get responses and even display the data on my screen, so I have no faulty code. I am currently using this to try and get the result content: comment.reviews.review
This is my complete code:
function Home() {
const [comments, setComments] = useState([]);
useEffect(() => {
fetchComments();
}, []);
useEffect(() => {
console.log(comments);
}, [comments]);
const fetchComments = async () => {
const response = await axios(
"https://store.steampowered.com/appreviews/1389990?json=1&language=english"
);
setComments(response.data);
};
var limitComments = comments.slice(0, 3);
return (
{limitComments &&
limitComments.map((comment) => (
<p>{comment.reviews.review}</p>
))}
);
}
export default Home;
What is wrong with request? I have tried using different keys like comment.author.reviews.review.
I'm building an app with React and Firestore.
In one feature, I need to use some specific user data to query data from another collection, and show that on the app.
Specifically I want to use users.books, which returns an array, to query the collection books.
However, for some reason the users.books doesn't load on first render. It typically takes 2-3 renders to fetch the books.user data. This is despite the currentUserUID being loaded right away.
I've tried using a loading state as specified in How to wait for Firebase data to be fetched before progressing?, but to no avail.
Do I need to use the onSnapShot method?
Thanks for reading
My code
import 'firebase/firestore'
import { booksRef} from '../../App';
const ProfileScreen = ({ navigation }) => {
const currentUserUID = firebase.auth().currentUser.uid;
const [firstName, setFirstName] = useState('');
const [userBookTitles, setUserBookTitles] = useState([]);
const [userBooks, setUserBooks] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function getUserInfo(){
let doc = await firebase
.firestore()
.collection('users')
.doc(currentUserUID)
.get();
if (!doc.exists){
Alert.alert('No user data found!')
} else {
let dataObj = doc.data();
setFirstName(dataObj.firstName)
setUserBookTitles(dataObj.books)
console.log(userBookTitles)
}
}
getUserInfo();
}, [])
useEffect(() => {
async function getUserBooks() {
booksRef.where("title", "in", userBookTitles).onSnapshot(snapshot => (
setUserBooks(snapshot.docs.map((doc) => ({id: doc.id, ...doc.data()})))
))
}
setLoading(false);
getUserBooks()
}, [])
if (!loading) {
return (
<View style={styles.container}>
<Text> Hi {firstName} </Text>
<TouchableOpacity onPress={handlePress}>
<Text> Log out </Text>
</TouchableOpacity>
<Row
books={userBooks}
/>
</View>
);
} else {
return (
<View style={styles.container}>
<Text> Test </Text>
</View>
);
}
};
So it's worth noting that your setX methods may, or may not, complete in the sequence you have them in your code. Therefore, your booksRef call could be being made even though userBookTitles is an empty array. Which would explain why you're not getting any data on load.
You're setting userBookTitles in your first useEffect and the only other place I see you're using it is in your booksRef call. One easy fix would be to simple move booksRef inside the else statement of the first useEffect and simply pass it the userBookTitles there. This should help in solving your issue, if I understood it correctly.
I am trying to render a component within a component file that relies on data from an outside API. Basically, my return in my component uses a component that is awaiting data, but I get an error of dataRecords is undefined and thus cannot be mapped over.
Hopefully my code will explain this better:
// Component.js
export const History = () => {
const [dateRecords, setDateRecords] = useState(0)
const { data, loading } = useGetRecords() // A custom hook to get the data
useEffect(() => {
fetchData()
}, [loading, data])
const fetchData = async () => {
try {
let records = await data
setDateRecords(records)
} catch (err) {
console.error(err)
}
}
// Below: Render component to be used in the component return
const GameItem = ({ game }) => {
return <div>{game.name}</div>
}
// When I map over dateRecords, I get an error that it is undefined
const renderRecords = async (GameItem) => {
return await dateRecords.map((game, index) => (
<GameItem key={index} game={game} />
))
}
const GameTable = () => {
return <div>{renderRecords(<GameItem />)}</div>
}
return(
// Don't display anything until dateRecords is loaded
{dateRecords? (
// Only display <GameTable/> if the dateRecords is not empty
{dateRecords.length > 0 && <GameTable/>
)
)
}
If dateRecords is meant to be an array, initialize it to an array instead of a number:
const [dateRecords, setDateRecords] = useState([]);
In this case when the API operation is being performed, anything trying to iterate over dateRecords will simply iterate over an empty array, displaying nothing.
You've set the initial state of dateRecords to 0 which is a number and is not iterable. You should set the initial state to an empty array:
const [dateRecords, setDateRecords] = useState([]);
I'm trying to build a custom hook to fetch data.
This is my App.js:
const [loadData, mainCategories] = useCustomHook();
useEffect(() => {
loadData();
}, []);
return (
<FlatList
data={mainCategories}
renderItem={({ item }) => {
return (
<View>
<Text>{item.name}</Text>
</View>
);
}}
/>
);
};
This is my useCustomHook.js:
const useCats = () => {
const [mainCategories, setMainCategories] = useState();
const loadData = async () => {
let response = await fetch(
`URL/read.php`
);
let results = await response.json();
setMainCategories(results.data);
};
return [loadData, mainCategories];
};
export default useCustomHook;
It''s working fine. I'm returning and exporting loadData and mainCategories from my useCustomHook.js and I'm getting both in App.js to use it there.
Now comes the part I'm struggling with:
Let's say I need a constant from App.js in the useCustomHook.js. In my case I'm getting an ID in App.js (forwarded by react-navigation from the previous screen) which I need in the URL like so:
URL/read.php?id=${id}
Is there any way to get that ID in useCustomHook.js?
You can pass it as a parameter. Try below
const useCats = () => {
const [mainCategories, setMainCategories] = useState();
const loadData = async (id) => {
let response = await fetch(
`URL/read.php?id=${id} `
);
let results = await response.json();
setMainCategories(results.data);
};
return [loadData, mainCategories];
};
What i want to make is a bookmark list, but i don't know how i can save an array of items in AsyncStorage, my skills are basic on react.
I just need the function to save posts (post image, title and id) when i press the button "Save to bookmark".
export default class PostDetails extends Component {
constructor(props) {
super(props);
const {params} = props.navigation.state;
this.state = {
item: params.item
};
}
render() {
const {item} = this.state;
return (
<Image source={{uri: item.post_image}}/>
<Text> {item.post_id} </Text>
<Text> {item.post_title} </Text>
<Button>
<Text> Save to Bookmark </Text>
</Button>
);
}
}
I think you want to use JSON.stringify(arrayToSave); see the docs for JSON.stringify(). It will convert the array to a JSON string that can be saved to AsyncStorage and then can be retrieved at a later stage.
const saveBookmarks = async (bookmarksArray) => {
try {
const bookmarksString = JSON.stringify(bookmarksArray);
await AsyncStorage.setItem('#MyStore:bookmarks',bookmarksString);
} catch (error) {
// Error saving data
}
};
<Button onClick={() => saveBookmarks(yourArray)} />
To retrieve it you can use const theSavedArray = JSON.parse(stringFromAsyncStorage); the docs for JSON.parse()
try {
const bookmarksString = await AsyncStorage.getItem('#MyStore:bookmarks');
if (bookmarksString !== null){
// We have data!!
const bookmarksArray = JSON.parse(bookmarksString);
}
} catch (error) {
// Error retrieving data
}