createEntityAdapter "updateOne" API doesn't work, data won't update? Where am I doing wrong?
codesandbox:
https://codesandbox.io/s/hopeful-kowalevski-yet3g
import React from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
import {
configureStore,
createSlice,
createEntityAdapter
} from '@reduxjs/toolkit';
const todosAdapter = createEntityAdapter();
const todosSlice = createSlice({
name: 'todos',
initialState: todosAdapter.getInitialState(),
reducers: {
todoAdded: todosAdapter.addOne,
todoUpdated: todosAdapter.updateOne
}
});
const { todoAdded, todoUpdated } = todosSlice.actions;
const store = configureStore({
reducer: { todos: todosSlice.reducer }
});
const Updated = () => {
const dispatch = useDispatch();
const todos = useSelector(store => store.todos);
console.log('todos: ', todos);
return (
<div>
<button onClick={() => dispatch(todoAdded({ id: 1, todo: 'one' }))}>
todoAdded
</button>
<button onClick={() => dispatch(todoUpdated({ id: 1, todo: 'two' }))}>
todoUpdated
</button>
<h5>Todos: {JSON.stringify(todos)}</h5>
</div>
);
};
export default () => (
<Provider store={store}>
<Updated />
</Provider>
);
It looks like you're using the API the wrong way.
updateOne takes a parameter that looks like this:
export type Update<T> = { id: EntityId; changes: Partial<T> }
So, you _should_ be dispatching:
dispatch(todoUpdated({id: 1, changes: {todo: "two"}))
I'm disturbed that TS isn't catching that.
@phryneas , do we need to do something similar to the EntityState tweaks to ensure that the user is passing in the right type here? Do any of the other CRUD methods need similar changes?
As a side note, this is a good use case for using upsertOne as it's easier to deal with.
@phryneas , do we need to do something similar to the
EntityStatetweaks to ensure that the user is passing in the right type here? Do any of the other CRUD methods need similar changes?
That's JavaScript code. You just reached the level of not even considering the possibility of someone using plain JS any more, welcome to my world :rofl:
Oh duh :)
Yeah, @ouweiya : ultimately the issue is you're dispatching a wrong payload, from plain JS, and so it's not getting caught by the TS compiler.
Would be helpful to add the sample code above to the documentation; I only read
In other words, they accept a state that looks like
{ids: [], entities: {}}, and calculate and return a new state.
and then wondered for quite a while why I can addOne, but updateOne doesn't seem to do anything. No one to blame but myself of course for not RTFMing - the info is clearly in there; one short piece of sample code IMO would better catch the eye, though...
@dd-ssc yeah, the createEntityAdapter doc page could use some more examples. Could you file a PR that adds some?
Was just about to update my comment above; you beat me to it. Didn't comment there, but you really helped me a lot with your clarification on enhancers / middleware and I'd like to return the favor; as soon as the customer is happy with the next release of the app, I'll try to make time and send a PR.
Most helpful comment
As a side note, this is a good use case for using
upsertOneas it's easier to deal with.