简体   繁体   English

如何将应用状态从 React Context 迁移到 Redux Tool Kit?

[英]How to migrate app state from React Context to Redux Tool Kit?

What I'm trying to achieve:我正在努力实现的目标:

I have a NextJS + Shopify storefront API application.我有一个 NextJS + Shopify 店面 API 应用程序。 Initially I set up a Context api for the state management but it's not that efficient because it re-renders everything what's wrapped in it.最初,我为状态管理设置了一个 Context api,但效率不高,因为它重新渲染了其中包含的所有内容。 Thus, I'm moving all state to the Redux Toolkit.因此,我将所有状态移至 Redux Toolkit。

Redux logic is pretty complex and I don't know all the pitfalls yet. Redux 逻辑非常复杂,我还不知道所有的陷阱。 But so far I encounter couple problems.但到目前为止,我遇到了几个问题。 For example in my old Context API structure I have couple functions that take a couple arguments :例如,在我旧的 Context API 结构中,我有几个函数接受几个参数

    const removeFromCheckout = async (checkoutId, lineItemIdsToRemove) => {
        client.checkout.removeLineItems(checkoutId, lineItemIdsToRemove).then((checkout) => {
            setCheckout(checkout);
            localStorage.setItem('checkout', checkoutId);
        });
    }

    const updateLineItem = async (item, quantity) => {
        const checkoutId = checkout.id;
        const lineItemsToUpdate = [
            {id: item.id, quantity: parseInt(quantity, 10)}
        ];
        client.checkout.updateLineItems(checkoutId, lineItemsToUpdate).then((checkout) => {
            setCheckout(checkout);
        });
    }

One argument ( checkoutId ) from the state and another one ( lineItemIdsToRemove ) extracted through the map() method.一个参数 ( checkoutId ) 来自状态,另一个参数 ( lineItemIdsToRemove ) 通过map()方法提取。 Inside actual component in JSX it looks and evokes like this:在 JSX 中的实际组件内部,它看起来和唤起如下:

<motion.button 
    className="underline cursor-pointer font-extralight"
    onClick={() => {removeFromCheckout(checkout.id, item.id)}}
>

How can I declare this type of functions inside createSlice({ }) ?如何在 createSlice({ }) 中声明这种类型的函数? Because the only type of arguments reducers inside createSlice can take are (state, action) .因为 createSlice 中的 reducers 可以采用的唯一类型的参数是(state, action) And also is it possible to have several useSelector() calls inside one file?一个文件中是否可以有多个 useSelector() 调用?

I have two different 'Slice' files imported to the component:我有两个不同的“切片”文件导入到组件中:

    const {toggle} = useSelector((state) => state.toggle);
    const {checkout} = useSelector((state) => state.checkout);

and only the {checkout} gives me this error: TypeError: Cannot destructure property 'checkout' of 'Object(...)(...)' as it is undefined.只有 {checkout} 给了我这个错误: TypeError: Cannot destructure property 'checkout' of 'Object(...)(...)' as it is undefined.

Thank you for you're attention, hope someone can shad the light on this one.感谢您的关注,希望有人能在这方面有所作为。

You can use the prepare notation for that:您可以为此使用准备符号

const todosSlice = createSlice({
  name: 'todos',
  initialState: [] as Item[],
  reducers: {
    addTodo: {
      reducer: (state, action: PayloadAction<Item>) => {
        state.push(action.payload)
      },
      prepare: (id: number, text: string) => {
        return { payload: { id, text } }
      },
    },
  },
})

dispatch(todosSlice.actions.addTodo(5, "test"))

But 99% of the cases you would probably stay with the one-parameter notation and just pass an object as payload, like但是在 99% 的情况下,您可能会继续使用单参数表示法,而只是将对象作为有效负载传递,例如

dispatch(todosSlice.actions.addTodo({ id: 5, text: "test"}))

as that just works out of the box without the prepare notation and makes your code more readable anyways.因为它只是开箱即用,没有准备符号,并且无论如何都会使您的代码更具可读性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM