redux 未捕获的类型错误:分派程序.useSyncExternalStore不是函数

juud5qan  于 2022-11-12  发布在  其他
关注(0)|答案(5)|浏览(182)

我正在尝试使用useSelector和useDispatch更改bulma模型的状态
就像这样

const isState = useSelector((state) => state.isActiveState)

Model.js为:

import React from 'react'
import "../CSS/Careers.css"
import { useSelector, useDispatch } from 'react-redux';
import { stateCheck } from '../Redux/ActiveState'

export default function Modal() {

      const isState = useSelector((state) => state.isActiveState)

      const dispatch  = useDispatch()

  return (
    <div>
      <div
        style={{ padding: "0rem 0.5rem 0rem" }}
        className={`modal ${isState}`}    //this should change the state to 'is-active'
      >
        <div onClick={() => dispatch(stateCheck())} className="modal-background"></div>
        <div style={{ borderRadius: "1.5rem" }} className="modal-card">
          <header
            style={{
              borderBottom: "1px solid white",
              backgroundColor: "#F2F5FF",
            }}
            className=""
          >
            <div style={{ padding: "17px 19px 20px" }} className="is-flex ">
              <p
                style={{ color: "#7209B7" }}
                className="modal-card-title has-text-weight-semibold"
              >
                Apply For Job
              </p>
              <button
                onClick={() => dispatch(stateCheck())}
                className="delete"
                aria-label="close"
              ></button>
            </div>
          </header>
          <section
            style={{ backgroundColor: "#F2F5FF" }}
            className="modal-card-body"
          >
            <div style={{ padding: "0rem 3rem 0rem" }} className="field">
              <div className="control has-icons-left ">
                <input
                  className="input "
                  // style={{ width: "100%" }}
                  type="text"
                  placeholder="Name"
                />
                <span className="icon is-small is-left">
                  <i className="fas fa-user"></i>
                </span>
              </div>
            </div>

            <div style={{ padding: "0rem 3rem 0rem" }} className="field">
              <div className="control has-icons-left ">
                <input className="input " type="email" placeholder="Email" />
                <span className="icon is-small is-left">
                  <i className="fas fa-envelope"></i>
                </span>
              </div>
            </div>
            <div
              style={{ padding: "0rem 3rem 0rem" }}
              className="file is-medium"
            >
              <label style={{ border: "3px sold #7209B7" }} className="">
                <input className="file-input" type="file" name="resume" />
                <span
                  style={{ backgroundColor: "#F2F5FF" }}
                  className="file-cta"
                >
                  <span className="file-icon">
                    <i
                      style={{ color: "#7209B7" }}
                      className="fas fa-upload"
                    ></i>
                  </span>
                  <span style={{ color: "#7209B7" }} className="file-label">
                    Choose a file…
                  </span>
                </span>
              </label>
            </div>
            <p
              style={{
                padding: "0rem 3rem 0rem",
                fontSize: "15px",
                color: "#fcb01a",
              }}
            >
              Select CV or Resume
            </p>
          </section>
          <footer
            style={{
              borderTop: "1px solid white",
              textAlign: "center",
              height: "20%",
              backgroundColor: "#F2F5FF",
            }}
            className=" has-text-centered"
          >
            <div
              style={{ paddingTop: "9px", textAlign: "center" }}
              className=""
            >
              <button style={{ backgroundColor: "#fcb01a" }} className="button">
                Submit
              </button>
            </div>
          </footer>
        </div>
      </div>

    </div>
  )
}

我的redux文件ActiveState.js是:

import { createSlice } from '@reduxjs/toolkit'

export const ActiveState = createSlice({
    name: 'isActiveState',
    initialState: {
      value: 0,
    },

    reducers: {
        stateCheck: (state) => {
          // Redux Toolkit allows us to write "mutating" logic in reducers. It
          // doesn't actually mutate the state because it uses the Immer library,
          // which detects changes to a "draft state" and produces a brand new
          // immutable state based off those changes

          if (state.value == 0){ 
               state.value = 'is-active';
            //   console.log(state.value)        

            }
            else{
                state.value = 0;
                // console.log(state.value)        

            }

        }

      },
    })

    export const { stateCheck } = ActiveState.actions;

    export default ActiveState.reducer;

并且store.js为:

import { configureStore } from '@reduxjs/toolkit'
import ActiveState from './components/Redux/ActiveState'

export default configureStore({
  reducer: {

    stateChecker : ActiveState,

  },
})

索引. js为:

import React from 'react';
import ReactDOM from 'react-dom';
import './components/CSS/index.css';
import App from './App';
import store from './store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>   
       <App />
    </Provider>

  </React.StrictMode>,
  document.getElementById('root')
);

我已经将model添加到组件中,并在组件中使用它,以触发我使用的model:

onClick={() => dispatch(stateCheck())}

调度工作正常,我已使用console.log进行检查
问题是,当我尝试使用以下语句获取redux状态时:

const isState = useSelector((state) => state.isActiveState)

我在控制台中收到以下错误:

Uncaught TypeError: dispatcher.useSyncExternalStore is not a function

我正在跟踪redux官方文档:
https://react-redux.js.org/tutorials/quick-start
我已经尝试了一切,检查导入,检查语法和关键字,并检查了StackOverflow上的每一个答案,但我仍然得到这个错误。
请帮帮我我被困在这里快一天了。

uttx8gqw

uttx8gqw1#

发生这种情况是因为React 18**(React和React Native)尚不支持react-redux**。
react-redux降级到以前的版本将解决您的问题。
对我来说,我的React Native项目降级了:

"react-redux": "^8.0.1",

"react-redux": "^7.2.8",
lhcgjxsq

lhcgjxsq2#

完整代码

索引.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './store/store';

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>
    </React.StrictMode>,
    document.getElementById('root')
);

模态.js

// import '../CSS/Careers.css';
import React from 'react';
import { Button } from 'antd';
import { useSelector, useDispatch } from 'react-redux';
import { stateCheck } from './store/slice';

export default function Modal() {
    const isState = useSelector((state) => state.stateChecker);
    const dispatch = useDispatch();

    console.log(isState);

    return (
        <div>
            <Button onClick={() => dispatch(stateCheck(true))}>Open</Button>
            <div
                style={{
                    padding: '0rem 0.5rem 0rem',
                    // display: isState.value ? 'block' : 'none'
                }}
                className={`modal ${isState.value ? 'is-active' : ''}`} //this should change the state to 'is-active'
            >
                <div onClick={() => dispatch(stateCheck(false))} className='modal-background'></div>
                <div style={{ borderRadius: '1.5rem' }} className='modal-card'>
                    <header
                        style={{
                            borderBottom: '1px solid white',
                            backgroundColor: '#F2F5FF'
                        }}
                        className=''
                    >
                        <div style={{ padding: '17px 19px 20px' }} className='is-flex '>
                            <p style={{ color: '#7209B7' }} className='modal-card-title has-text-weight-semibold'>
                                Apply For Job
                            </p>
                            <button onClick={() => dispatch(stateCheck(false))} className='delete' aria-label='close'></button>
                        </div>
                    </header>
                    <section style={{ backgroundColor: '#F2F5FF' }} className='modal-card-body'>
                        <div style={{ padding: '0rem 3rem 0rem' }} className='field'>
                            <div className='control has-icons-left '>
                                <input
                                    className='input '
                                    // style={{ width: "100%" }}
                                    type='text'
                                    placeholder='Name'
                                />
                                <span className='icon is-small is-left'>
                                    <i className='fas fa-user'></i>
                                </span>
                            </div>
                        </div>

                        <div style={{ padding: '0rem 3rem 0rem' }} className='field'>
                            <div className='control has-icons-left '>
                                <input className='input ' type='email' placeholder='Email' />
                                <span className='icon is-small is-left'>
                                    <i className='fas fa-envelope'></i>
                                </span>
                            </div>
                        </div>
                        <div style={{ padding: '0rem 3rem 0rem' }} className='file is-medium'>
                            <label style={{ border: '3px sold #7209B7' }} className=''>
                                <input className='file-input' type='file' name='resume' />
                                <span style={{ backgroundColor: '#F2F5FF' }} className='file-cta'>
                                    <span className='file-icon'>
                                        <i style={{ color: '#7209B7' }} className='fas fa-upload'></i>
                                    </span>
                                    <span style={{ color: '#7209B7' }} className='file-label'>
                                        Choose a file…
                                    </span>
                                </span>
                            </label>
                        </div>
                        <p
                            style={{
                                padding: '0rem 3rem 0rem',
                                fontSize: '15px',
                                color: '#fcb01a'
                            }}
                        >
                            Select CV or Resume
                        </p>
                    </section>
                    <footer
                        style={{
                            borderTop: '1px solid white',
                            textAlign: 'center',
                            height: '20%',
                            backgroundColor: '#F2F5FF'
                        }}
                        className=' has-text-centered'
                    >
                        <div style={{ paddingTop: '9px', textAlign: 'center' }} className=''>
                            <button style={{ backgroundColor: '#fcb01a' }} className='button'>
                                Submit
                            </button>
                        </div>
                    </footer>
                </div>
            </div>
        </div>
    );
}

切片.js

import { createSlice } from '@reduxjs/toolkit';

export const ActiveState = createSlice({
    name: 'isActiveState',
    initialState: {
        value: false
    },

    reducers: {
        stateCheck: (state, action) => {
            state.value = action.payload;
        }
    }
});

export const { stateCheck } = ActiveState.actions;
export default ActiveState.reducer;

存储.js

import { configureStore } from '@reduxjs/toolkit';
import ActiveState from './slice';

export default configureStore({
    reducer: {
        stateChecker: ActiveState
    }
});

它不是isActiveState。您应该使用在configureStore中指定的reducer的名称。stateChecker

const isState = useSelector((state) => state.stateChecker)

现在isState将具有value

qq24tv8q

qq24tv8q3#

为什么要使用“ReactDOM.render”?您使用了React18附带一种名为useSyncExternalStore的技术。您不需要使用ReactDOM.createRoot(元素,选项).render(组件)吗?

ewm0tg9j

ewm0tg9j4#

yarn add react@17.0.2

将React18降级为React17

eimct9ow

eimct9ow5#

我有同样的问题,因为我有"react-dom": "^17.0.1",而Reactv18安装。我的设置是这样的:

import ReactDOM from "react-dom";

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

我将设置切换为:

import { createRoot } from "react-dom/client";

const container = document.getElementById("root");
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

它工作。包版本

"react-redux": "^8.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",

相关问题