Диспетчеризация, вызывающая TypeError «прослушиватель2, не является функцией»

Я просто пытаюсь отправить действие в хранилище и получаю эту ошибку. Я понятия не имею, что такое прослушиватель2 и почему возникает ошибка типа:

listener2 is not a function
TypeError: listener2 is not a function
    at wrappedListener
    at Map.forEach (<anonymous>)
    at Object.dispatch
    at dispatch
    at App

Это мой единственный кусочек:

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

const PostContainerSlice = createSlice({
  name: "postContainer",
  initialState: [],
  reducers: {
    addPost: (state, action) => {
      state.push(action.payload)
    },
  }
})

export const {addPost} = PostContainerSlice.actions;
export default PostContainerSlice.reducer;

магазин.js:

import {configureStore} from '@reduxjs/toolkit';
import PostContainerReducer from './features/post/PostContainerSlice.js';

export default configureStore({
  reducer: {
    postContainer: PostContainerReducer
  }
})


индекс.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import store from './store.js';

const root = ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
      <App dispatch = {store.dispatch} state = {store.getState()} />
  </React.StrictMode>
);

store.subscribe(root);

Приложение.js:

import './App.css';
import PostContainer from './features/post/PostContainer'

function App(props) {
  const {state, dispatch} = props;

  dispatch({
    type: 'postContainer/addPost',
    payload: 'test'
  })
  console.info(state)

 
}

export default App;

Консольная регистрация состояния магазина работает нормально, причиной этого является просто диспетчеризация. При удалении «store.subscribe(root)» из index.js ошибка не возникает, но журналирование консоли показывает, что ничего не было отправлено и хранилище остается неизменным... возможно, это не имеет никакого отношения к проблеме. Кроме того, при отправке и регистрации состояния из index.js над рендерингом приложения магазин, похоже, отправляет и регистрирует нормально... подумал, что это подсказка, но ни к чему не привел.

🤔 А знаете ли вы, что...
React обеспечивает высокую производительность благодаря эффективной обработке изменений DOM.


1
54
1

Ответ:

Решено

Проблема

«Слушатель», о котором здесь идет речь, — это функция обратного вызова слушателя, которая ожидает передачи.

Смотрите подписывайтесь(слушатель)

store.subscribe не возвращает функцию.

const root = ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
      <App dispatch = {store.dispatch} state = {store.getState()} />
  </React.StrictMode>
);

store.subscribe(root); // root is not a function

Решение

Возможно, вам удастся обойтись созданием функции, которая отображает приложение, которое также может функционировать как обратный вызов прослушивателя.

Пример:

const root = ReactDOM.createRoot(document.getElementById('root'));

const renderApp = () => { 
  root.render(
    <React.StrictMode>
      <App dispatch = {store.dispatch} state = {store.getState()} />
    </React.StrictMode>
  );
};

renderApp(); // <-- call once to initially render app

store.subscribe(renderApp); // <-- pass as listener to rerender with state changes

Примечание. Однако мы используем Redux в React не так!

Вам следует импортировать и обернуть компонент ReactDOM.createRoot().render в компонент Appreact-redux, чтобы предоставить контекст хранилища Redux приложению React.

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

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

Компонент Provider и все компоненты в суб-ReactTree должны импортировать и использовать хуки App и useDispatch из useSelector для отправки действий в хранилище и подписки на выбранные обновления состояния.

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import './App.css';
import PostContainer from './features/post/PostContainer'

function App() {
  const dispatch = useDispatch();
  const postContainer = useSelector(state => state.postContainer);

  useEffect(() => {
    dispatch({
      type: 'postContainer/addPost',
      payload: 'test'
    });
  }, [dispatch]);

  useEffect(() => {
    console.info({ postContainer });
  }, [postContainer]);
 
  ...
}

export default App;