首页 > 解决方案 > React Hooks reducer 导致内存泄漏

问题描述

我有一个 React 组件,它在初始化时调用 reducer 来填充一个数组,其中包含与 firebase db 中指定的数字一样多的空白记录。如果 firebase db 字段 myArray 长度为 5,则组件将初始化并调用 reducer 在上下文中的数组中创建 5 条空白记录:

import React, { useState, useEffect, useContext } from 'react';
import { useHistory, useLocation } from 'react-router';

import ArrayCard from '../../../containers/ArrayCard';
import firebase from '../../../Utils/firebase';
import MyContext from '../../../Utils/contexts/MyContext ';

import { initialiseMyArray, changeArray} from '../../../Utils/reducers/MyActions';

function MyComponent() {
    const { push } = useHistory();
    const location = useLocation();
    const context = useContext(MyContext);
    const dispatch = context.dispatch;

    const session = location.state.currentSession;
    const sessionRef = firebase.firestore().collection("sessions").doc(session);

    const [ loaded, setLoaded ] = useState(false);

    const [ myArray, setMyArray] = useState([]);
    const [ myArrayCurrentIndex, setMyArrayCurrentIndex ] = useState();

const getSessionData = () => {
        sessionRef.get().then(function(doc) {
            if (doc.exists) {
                const myArrayLength= parseInt(doc.data().myArrayLength);
                dispatch({ type: initialisePensionsFromFirebase, myArrayLength: myArrayLength});
                setMyArrayCurrentIndex (0);
                setLoaded(true);
            } else {
                // doc.data() will be undefined in this case
                console.log("No such document!");
            }
        }).catch(function(error) {
            console.log("Error getting document:", error);
        });
    }

useEffect(() => {
        if (sessionRef && !loaded && myArray.length < 1) {
            getSessionData();
        }
        if (context) {
            console.log("CONTEXT ON PAGE: ", context)
        }
    }, [loaded, currentIndex])

上下文中新创建的 myArray 的索引 currentIndex 用于填充此组件内的组件:

return (
    <innerComponent
    handleAmendSomeproperty={(itemIndex, field, value) => handleAmendSomeproperty(itemIndex, field, value)}
    itemIndex={currentIndex}
    someproperty={context.state.someitem[currentIndex].someproperty}
></innerComponent>
)

我希望能够修改 myArray[currentIndex] 中的 someproperty 字段,但我的调度会导致无休止的重新渲染。

const handleAmendSomeproperty= (itemIndex, field, value) => {
         dispatch({ type: changeItem, itemIndex: itemIndex});
    }

我的减速机开关盒是这样的:

case initialiseMyArray:
        console.log("SRSTATE: ", state);
        let _initialArray = []
        for (let i=0; i<action.myArrayLength; i++) {
            _initialArray .push(
                {
                    itemIndex: i,
                    someproperty: ""                    }
            )
        }
        return {
            ...state,
            someproperty: [..._initialArray ]
        };
    case changeArray:
       // I want to leave the state untouched at this stage until I stop infinite rerenders
        return {
            ...state
        };

发生了什么导致无限重新渲染?为什么我不能修改一些属性,但是在状态下初始化新数组可以正常工作?

innerComponent 有很多这样的版本:

<div>
                        <label>{label}</label>
                        <div onClick={() => handleAmendSomeproperty(itemIndex, "fieldName", "fieldValue")}>
                            {someproperty === "booleanValue" ? filled : empty}
                        </div>
                    </div>

和很多这样的:

<input
                        type="text"
                        placeholder=""
                        value={somepropertyvalue}
                        onChange={(event) => handleAmendSomeproperty(itemIndex, "fieldName", event.target.value)}
                    />

标签: reactjsreact-hooksreact-context

解决方案


推荐阅读