setState and original() function
Perhaps I am confused of the usage, but what I am trying basically to achieve is to get the "original" / "initial" data to update the draft with.
const orders = {
data: dataRowsMockData // array of objects
};
// in parent component , passing `setOrdersData` as a prop.
const [ordersData, setOrdersData] = useMutative<{ data: BuySellOrderType[] }>(
orders
);
// In child component
serOrdersData((draft) => {
const origin = original(draft.data);
draft.data = origin.filter(
(order) => order.coin === data.id
);
// shouldn't origin be always the "original" initial data?
});
So in this function what I am trying to achieve is to filter items in a list, I want to keep the original data before the update/filter so I can just keep filtering from the "source".
Of course I am aware of how to achieve this in the "react way" however, I thought using original() inside the update function would work as expected.
const origin = original(draft.data) will always be the same reference as the original state.
I think your usage is correct. In contrast, if you don't use original(), then if this list is too large, the filter operation would mean additional draft instantiation.
Therefore, your approach is theoretically more efficient when you're only modifying the list, as it performs the operation in a more optimized way.
@unadlib
Perhaps the issue was not clear but original() does not seem work, since the data becomes the same as "drafted" I mean, the data gets mutated, it does not work as I would expect.
Is it because of prop drilling?
@irv-armenta-g , could you provide a test case?
I tried to build a possible test case and it is passing.
const dataRowsMockData = [
{
coin: 'BTC',
price: 10000,
quantity: 1,
},
{
coin: 'ETH',
price: 20000,
quantity: 2,
},
];
type BuySellOrderType = {
coin: string;
price: number;
quantity: number;
};
const orders = {
data: dataRowsMockData,
};
const data = {
id: 'ETH',
};
const { result } = renderHook(() =>
useMutative<{ data: BuySellOrderType[] }>(orders)
);
const [ordersData, setOrdersData] = result.current;
act(() => {
setOrdersData((draft) => {
const origin = original(draft.data);
expect(origin).toBe(dataRowsMockData);
expect(origin).not.toBe(draft.data);
draft.data = origin.filter((order) => order.coin === data.id);
});
});
const [nextState] = result.current;
expect(nextState).toEqual({
data: [
{
coin: 'ETH',
price: 20000,
quantity: 2,
},
],
});
In this example:
setOrdersData((draft) => {
const origin = original(draft.data);
expect(origin).toBe(dataRowsMockData);
draft.data = origin.filter((order) => order.coin === data.id);
expect(origin).not.toBe(draft.data); // Will this pass?
});
The next time I call setOrdersData will const origin value will be expect(origin).toBe(dataRowsMockData); ?
That is my issue, I assume origin to be "always" -> dataRowsMockData ?
@irv-armenta-g
I think you might be misunderstanding the filter operation, it is an immutable operation.
A shallow copy of the given array containing just the elements that pass the test. If no elements pass the test, an empty array is returned.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#return_value