aws-sdkaws-amplifyaws-appsyncaws-amplify-sdk-js

<Connect /> re-renders onSubscriptionMsg, but not with new data


I have a really simple component using Connect from aws-amplify-react

const EmployeeExpensesTable = () => {
  const [user, setUser] = useState(null)
  useEffect(() => { Auth.currentAuthenticatedUser().then(user => setUser(user)) }, [])
  console.log(user)

  if(!user) { return null }

  return (
    <Connect

      query={graphqlOperation(queries.listTransactions, { owner: user.username })}

      subscription={graphqlOperation(subscriptions.onCreateTransaction, { owner: user.username })}

      onSubscriptionMsg={(prev, { onCreateTransaction }) => {
        console.log('oncreatetransaction:', onCreateTransaction)
        console.log('prev', prev)
        return onCreateTransaction
      }}

    >
      {
        ({ data: { listTransactions }, loading, errors }) => {

          console.log('transactions', listTransactions)

          if (errors.length) return (<h3>Error</h3>)

          if (loading || !listTransactions) return (<p>loading...</p>)

          return (<core.components.Table data={listTransactions.items} />)
        }
      }
    </Connect>
  )
}

export default EmployeeExpensesTable

I have an external ETL process that adds transactions to the DynamoDB table. The subscription is firing and my oncreatetransaction message is being displayed with the new data, and the Connect component re-renders, but it renders using it's original data, not the new data. What am I doing wrong?


Solution

  • Turns out that onSubscriptionMsg is like the reducer for the Connect component's state. You are given the previous value and the new value to the function and you need to return the new state.

    onSubscriptionMsg={(prev, data) => ({
            listTransactions: {
              items: [...prev.listTransactions.items.slice(-9), data.onCreateTransaction ]
            }
          })
    

    The above works great for me. The .slice(-9) is because I only care about the last 10 rows that were added.