'Error: too many re-renders' on simple React-Redux app

'Error: too many re-renders' on simple React-Redux app

我正在尝试使用 React-Redux 构建一个简单的应用程序,该应用程序从状态获取报价并将其呈现到页面。现在,我在一个名为 QuoteBox 的功能组件中拥有该应用程序的主要功能,我在另一个名为 App 的功能组件中呈现它,然后将其包装在 React-Redux Provider 中,最后呈现到页面中:

./src/features/QuoteBox/QuoteBox.jsx

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
  initialize,
  getNewQuote,
  selectQuote
} from './quoteBoxSlice'
import styles from './QuoteBox.module.css'

export function QuoteBox() {
  const currentQuote = useSelector(selectQuote)
  const dispatch = useDispatch()

  return (
    <div
      className={styles['quote-box']}
      onLoad={dispatch(initialize())}
      >
      <p className={styles['text']}>{currentQuote['quote']}</p>
      <p className={styles['author']}>{currentQuote['author']}</p>
      <button
        className={styles['new-quote']}
        onClick={dispatch(getNewQuote())}
        >New Quote!</button>
    </div>
  );
}

./src/features/QuoteBox/quoteBoxSlice.js

import { createSlice } from '@reduxjs/toolkit'

function randomIndex(n) {
  return Math.floor(Math.random() * n);
}

export const slice = createSlice({
  name: 'quotebox',
  initialState: {
    allQuotes: [],
    currentQuote: {}
  },
  reducers: {
    initialize: state => {
      state['allQuotes'] = [
        { author: 'Author One', quote: 'Quote One' },
        { author: 'Author Two', quote: 'Quote Two' },
        { author: 'Author Three', quote: 'Quote Three' },
        { author: 'Author Four', quote: 'Quote Four' },
        { author: 'Author Five', quote: 'Quote Five' }
      ]
      state['currentQuote'] = state['allQuotes'][
        randomIndex(state['allQuotes'].length)
      ]
    },
    getNewQuote: state => {
      state['currentQuote'] = state['allQuotes'][
        randomIndex(state['allQuotes'].length)
      ]
    }
  }
})

export const { initialize, getNewQuote } = slice.actions

export function selectQuote(state) {
  return state['quoteBox']['currentQuote'];
}

export default slice.reducer

./src/app/store.js

import { configureStore } from '@reduxjs/toolkit'
import quoteBoxReducer from '../features/QuoteBox/quoteBoxSlice'

export default configureStore({
  reducer: {
    quoteBox: quoteBoxReducer
  }
})

./src/App.jsx

import React from 'react'
import { QuoteBox } from './features/QuoteBox/QuoteBox'

function App() {  
  return (
    <div>
      <QuoteBox />
    </div>
  );
}

export default App

./src/index.js

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

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

错误页面给了我以下反馈:

**18 stack frames were expanded.**
**renderWithHooks**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:14815
**updateFunctionComponent**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:17034
**beginWork**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:18610
**callCallback**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:188
**invokeGuardedCallbackDev**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:237
**invokeGuardedCallback**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:292
**beginWork**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:23203
**performUnitOfWork**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:22157
**workLoopSync**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:22130
**performSyncWorkOnRoot**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:21756
**flushSyncCallbackQueueImpl/<**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:11089
**unstable_runWithPriority**
C:/Users/jpaul/Desktop/quote-box/node_modules/scheduler/cjs/scheduler.development.js:653
**runWithPriority**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:11039
**flushSyncCallbackQueueImpl**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:11084
**flushSyncCallbackQueue**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:11072
**unbatchedUpdates**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:21909
**legacyRenderSubtreeIntoContainer**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:24757
**render**
C:/Users/jpaul/Desktop/quote-box/node_modules/react-dom/cjs/react-dom.development.js:24840

什么可能导致这里出现无限循环?

在您的 QuoteBox 中,您是在渲染时调用调度,而不是在单击时调用。这会更改报价,导致 QuoteBox 的重新渲染,从而导致无限次的另一次调度。改变这个:

onClick={dispatch(getNewQuote())}

对此:

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