如何使用 redux tollkit 修复 Next 14 中的错误“请确保组件包裹在 <Provider> 中”?

问题描述 投票:0回答:1

我很难让 Next.js 14 与 Redux 一起使用

Provider
。我按照此处Redux官方文档上的所有说明进行操作,但我不断收到此错误:

错误:找不到react-redux上下文值;请确保 组件被包裹在

我在任何地方都找不到解决方案。 这些是我的结构和文件: - 应用程序 --StoreProvider.tsx --page.tsx --lib --store.ts --hooks.ts - 特征 - 柜台 --counterSlice.ts --计数器.tsx

StoreProivder.tsx

'use client'

import { useRef } from 'react'
import { Provider } from 'react-redux'
import { makeStore, AppStore } from '../lib/store'

export default function StoreProvider({
  children
}: {
  children: React.ReactNode
}) {
  const storeRef = useRef<AppStore>()
  if (!storeRef.current) {
    // Create the store instance the first time this renders
    storeRef.current = makeStore()
  }

  return <Provider store={storeRef.current}>{children}</Provider>
}

hooks.ts

import { useDispatch, useSelector, useStore } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch, AppStore } from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppStore: () => AppStore = useStore

store.ts

import { configureStore } from '@reduxjs/toolkit'

export const makeStore = () => {
  return configureStore({
    reducer: {}
  })
}

// Infer the type of makeStore
export type AppStore = ReturnType<typeof makeStore>
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<AppStore['getState']>
export type AppDispatch = AppStore['dispatch']

计数器.tsx

'use client'

import React, { useState } from 'react';
import { useAppSelector, useAppDispatch, useAppStore  } from '../../hooks';
import {
  decrement,
  increment,
  incrementByAmount,
  selectCount,
} from './counterSlice';
import styles from './Counter.module.css';

export function Counter() {
  const count = useAppSelector(selectCount);

  const dispatch = useAppDispatch();
  const [incrementAmount, setIncrementAmount] = useState('2');

  const incrementValue = Number(incrementAmount) || 0;

  return (
    <div>
      <div className={styles.row}>
        <button
          className={styles.button}
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          -
        </button>
        <span className={styles.value}>{count}</span>
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
      </div>
      <div className={styles.row}>
        <input
          className={styles.textbox}
          aria-label="Set increment amount"
          value={incrementAmount}
          onChange={(e) => setIncrementAmount(e.target.value)}
        />
        <button
          className={styles.button}
          onClick={() => dispatch(incrementByAmount(incrementValue))}
        >
          Add Amount
        </button>
      </div>
    </div>
  );
}

counterSlice.ts

import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { RootState } from '../../store';

export interface CounterState {
  value: number;
  status: 'idle' | 'loading' | 'failed';
}

const initialState: CounterState = {
  value: 0,
  status: 'idle',
};

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    },
  },

});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export const selectCount = (state: RootState) => state.counter.value;

export default counterSlice.reducer;

页面.tsx

import { Counter } from '../lib/features/counter/Counter'

export default function Home() {
  return (
    <Counter />
  )
}

错误在这里:Counter.js 中的

const count = useAppSelector(selectCount)
,它说我没有将其包装在
Provider
中,当我假设它是在 StoreProvider.tsx 中完成时,不是吗?

reactjs typescript next.js react-redux
1个回答
0
投票

你添加了这个库吗?

yarn add next-redux-wrapper
(了解更多这里)。 如果您使用npm而不是yarn,请使用此命令:
npm install next-redux-wrapper
该库允许您在客户端和服务器环境中使用 redux 的全局状态。

其他解决方案是仅在客户端组件中使用 redux 功能,方法是在所有使用 redux 的组件的顶部添加此语法。

"use client"
这样,redux 工作只会在客户端环境中使用,即简单 redux 的适合环境。 了解有关 Next 客户端组件的更多信息此处

© www.soinside.com 2019 - 2024. All rights reserved.