reactjs - 当两个状态变量更新时,组件渲染两次是否正常?

标签 reactjs

在我的测试应用程序中,每次调用某个函数时,都会调用我的 API (axios.get),然后使用从数据库接收到的数据更新两个状态变量。这两个状态变量都会改变屏幕上显示的部分内容。

事情是,我添加了一个 useEffect 钩子(Hook)来“调试”重新渲染的数量,我注意到该组件被重新渲染了两次,我猜是因为它一次用于一个状态变量,一次用于另一个状态变量。我认为使用 useReducer 会改变这一点,但事实并非如此。

这是正常的 React 行为还是我应该做一些不同的事情以便组件仅重新渲染一次?

编辑:我正在编辑以添加代码: (这是一个琐事测试应用程序,我是 React 新手,所以我正在练习)

import React, { useEffect, useReducer } from 'react'
import axios from 'axios'
import './App.css';
import reducer from './Reducer.js'

const initialState = {
    question: '',
    id: 1,
    choices: []
}

const Questions = () => {

    const [state, dispatch] = useReducer(reducer, initialState)

    useEffect(() => {
        console.log('executed');
    })


    const getQuestion = async (e) => {

        try {
            e.preventDefault()
            
            const res = await axios.get(`/questions/${state.id}`)
            
            dispatch({
                type: 'set_question',
                payload:
                    res.data.question
            })
            dispatch({
                type: 'set_choices',
                payload:
                    [res.data.correct_answer,
                    res.data.incorrect_answer1,
                    res.data.incorrect_answer2]
            })

        } catch (err) {
            console.log(err);
        }
    }


    return (
        <div>

            <form onSubmit={getQuestion}>
                <button>Get next question</button>
            </form>

            <h1> {state.question ? state.question : null}</h1>
            <button> {state.choices ? `${state.choices[0]}` : null}</button>
            <button> {state.choices ? ` ${state.choices[1]}` : null}</button>
            <button> {state.choices ? ` ${state.choices[2]}` : null}</button>
        </div>
    )
}

export default Questions

reducer :

const reducer = (state, action) => {

    switch (action.type) {

        case 'set_question':
            return {
                ...state,
                question: action.payload
            }

        case 'set_choices':
            return {
                ...state,
                choices: action.payload
            }

        default:
            return state

    }
}

export default reducer

最佳答案

React 仅在事件处理程序和生命周期方法中批量进行状态更新。如果状态更新发生在异步函数中,例如为了响应成功调用 fetch 或 setTimeout,它们不会被批处理。宣布这一点将在未来版本的 React 中进行更改。

另请参阅 Dan Abramov 对此的回答: https://stackoverflow.com/a/48610973/5005177

However, both in React 16 and earlier versions, there is yet no batching by default outside of React event handlers. So if in your example we had an AJAX response handler instead of handleClick, each setState() would be processed immediately as it happens. In this case, yes, you would see an intermediate state.

promise.then(() => {
    // We're not in an event handler, so these are flushed separately.
    this.setState({a: true}); // Re-renders with {a: true, b: false }
    this.setState({b: true}); // Re-renders with {a: true, b: true }
    this.props.setParentState(); // Re-renders the parent
});

如果您希望组件仅重新渲染一次,则必须将所有数据保留在单个状态对象中,以便您只需调用 setState 一次(或 dispatch(如果您想对新数据使用 useReducer)。

另一个解决方法是将状态更新 block 包装在 ReactDOM.unstable_batchedUpdates(() => {...}) 中,在未来的 React 版本中很可能不再需要它。有关详细信息,另请参阅上面 Dan Abramov 的回答。

关于reactjs - 当两个状态变量更新时,组件渲染两次是否正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62513753/

相关文章:

javascript - onClick后如何不刷新页面

javascript - 如何使用 useRef 和 react Hook 在 ReactJS 中设置对自定义输入的关注?

javascript - 如何使数组在Javascript中的不同函数下可访问?

reactjs - 是否可以通过使用 HOC(高阶组件)在类组件中使用 React Hooks?

javascript - TypeError : utils. requestSendSMSPermission 不是函数

javascript - JavaScript/React 中的构造函数是必需的吗?

javascript - 如何使用 React Router v4 访问 React 应用程序之外的历史实例?

javascript - React - 强制水平滚动

reactjs - 我是否必须在 react 项目中将 .env 文件添加到版本控制中?

javascript - 解析 json react native