I am trying to get data from a hook into my redux toolkit store.
I have other redux actions and reducers working that update the store when I request data from API endpoints, but for this I need to create and action/reducer for getting data from a hook.
When I call a hook on my page component it works fine and returns a value after it loads:
this (main component) works:
const account = "name";
const { data, isFetching } = useBalances(account);
<div>
Balances:
{isFetching ? (
"Fetching balances..."
) : (
<ul>
{data?.map((balance) => (
<li key={balance.title}>
{balance.amount} // this shows correctly after loading
</li>
))}
</ul>
)}
</div>;
Now when I tried to translate this into a redux action, it always fails and I get an error where I set a console log: getting redux error: true
I want to dispatch the action from the main component, which would then load the data from the hook. Then back on the main component it could show the data directly from the store.
Here is how the main component would look:
const dispatch = useAppDispatch();
const { amount, pending, error } = useAppSelector(accountsSelector);
{
pending && <p>Loading...</p>;
}
{
amount && <p>{"redux amount: " + amount}</p>;
}
{
error && console.log("getting redux error: " + error);
} // this shows
<button onClick={() => dispatch(getAccounts())} disabled={pending}>
get Accounts
</button>;
My redux action page:
export const getAccounts = createAsyncThunk("accounts/getBalance", async () => {
const account = "name";
const { data, isFetching } = useBalances(account);
try {
data?.forEach((balance) => {
if (balance.title == "name") {
return { amount: Number.parseInt(balance.amount) };
}
});
} catch (e) {}
return { amount: 0 };
});
my redux reducer page:
export type AccountsState = {
amount: number,
pending: boolean,
error: boolean,
};
const initialState: AccountsState = {
amount: 0,
pending: false,
error: false,
};
export const accountsReducer = createReducer(initialState, (builder) => {
builder
.addCase(getAccounts.pending, (state) => {
state.pending = true;
})
.addCase(getAccounts.fulfilled, (state, { payload }) => {
state.pending = false;
state.amount = payload.amount;
})
.addCase(getAccounts.rejected, (state) => {
state.pending = false;
state.error = true;
});
});
export default accountsReducer;
There are rules of hooks. You cannot call useBalances
inside createAsyncThunk
.
The solution is to take useBalances
asynchronous logic and use it directly from the payloadCreator
.