'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())}
我正在尝试使用 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())}