After I added async function getNumbers(owner)
I receive the following error
71 | <div className="App">
72 | Messages for user: {owner}
73 | <h3>Numbers</h3>
> 74 | <div>
| ^ 75 | {state.numbers.length > 0 ? (
76 | state.numbers.map(number => <p key={number.to}>{number.to}</p>)
77 | ) : (
The reason seems to be caused by async function getNumbers(owner)
.
import Amplify, { Auth, API, graphqlOperation } from "aws-amplify";
import React, { useEffect, useReducer, useState } from "react";
import { withAuthenticator } from "aws-amplify-react";
import { messagesByToByCreatedAt, numberByOwnerByTo } from "./graphql/queries";
import awsconfig from "./aws-exports";
import "./App.css";
Amplify.configure(awsconfig);
// Action Types
const QUERY = "QUERY";
const initialState = {
messages: [],
numbers: []
};
const reducer = (state, action) => {
switch (action.type) {
case QUERY:
return { ...state, messages: action.messages, numbers: action.numbers };
default:
return state;
}
};
function App() {
const [owner, setOwner] = useState(null);
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
// Get all numbers that belong to user
async function getNumbers(owner) {
const ownerData = await API.graphql(
graphqlOperation(numberByOwnerByTo, { owner: owner })
);
dispatch({
type: QUERY,
numbers: ownerData.data.numberByOwnerByTo.items
});
}
getNumbers("13d8fbce-8989-4dff-bdcf-2fac8926a52d");
// getMessages
async function getMessages(number) {
const messageData = await API.graphql(
graphqlOperation(messagesByToByCreatedAt, { to: number })
);
dispatch({
type: QUERY,
messages: messageData.data.messagesByToByCreatedAt.items
});
}
getMessages("4915735992273");
// Assign logged in user to $owner
Auth.currentAuthenticatedUser({
bypassCache: false
})
.then(user => {
setOwner(user.username);
})
.catch(err => console.log(err));
}, []);
return (
<div className="App">
Messages for user: {owner}
<h3>Numbers</h3>
<div>
{state.numbers.length > 0 ? (
state.numbers.map(number => <p key={number.to}>{number.to}</p>)
) : (
<p>Add numbers!</p>
)}
</div>
<h3>Messages</h3>
<div>
{state.messages.length > 0 ? (
state.messages.map(message => (
<p key={message.from}>{message.messageBody}</p>
))
) : (
<p>Add messages!</p>
)}
</div>
</div>
);
}
export default withAuthenticator(App, true);
Here how I could solve it. Thanks to @Arun K
useEffect(() => {
// getMessages
async function getData(number, owner) {
const messageData = await API.graphql(
graphqlOperation(messagesByToByCreatedAt, { to: number })
);
const ownerData = await API.graphql(
graphqlOperation(numberByOwnerByTo, { owner: owner })
);
dispatch({
type: QUERY,
numbers: ownerData.data.numberByOwnerByTo.items,
messages: messageData.data.messagesByToByCreatedAt.items
});
}
getData("4915735992273", "13d8fbce-8989-4dff-bdcf-2fac8926a52d");
It looks like to me that the ownerData.data.numberByOwnerByTo.items
is returning undefined
. the main issue seems to be that. you should fix that.
then your reducer is assigning undefined
to numbers
. numbers: action.numbers
you could assign the value if its not undefined or set it to an empty array
return { ...state, messages: action.messages, numbers: action.numbers || [] };
Also the state is updating twice, once for after each api calls, thats why the numbers
was undefined
when the component is rendered for messages
state update.
Could you do one state update after you fetch both messages and numbers.
dispatch({
type: QUERY,
numbers: ownerData.data.numberByOwnerByTo.items,
messages: messageData.data.messagesByToByCreatedAt.items
});