简体   繁体   English

上下文 state 被意外更新 - 反应 Typescript

[英]Context state being updated unexpectedly - React Typescript

First time poster so let me know if more information is need.第一次发帖,如果需要更多信息,请告诉我。

Trying to figure out why my global state using context API is being updated even when my setSate method is commented out.试图弄清楚为什么我的全局 state 使用上下文 API 正在更新,即使我的 setSate 方法被注释掉。 I thought i might have been mutating the state directly accidently but I dont believe I am我想我可能已经意外地直接改变了 state 但我不相信我是

"specialModes" in actionOnClick() is the state in question actionOnClick() 中的“specialModes”是有问题的 state

const SpecialFunctions: FC = (props: Props) => {
const { currentModeContext, specialModesContext: specialActionsContext, performCalc, inputValueContext } = useContext(AppContext)
const { specialModes, setSpecialModes } = specialActionsContext
const { currentMode, setCurrentMode } = currentModeContext
const { inputValue, setInputValue } = inputValueContext

const categoryOnClick = (index: number) => {
    setCurrentMode(specialModes[index])
    console.log(specialModes[index].title);
}

const actionOnClick = (action: IAction) => {
    let newAction = action
    newAction.value = performCalc()
    let newSpecialModes = specialModes.map((mode) => {
        if (mode === currentMode) {
            let newMode = mode
            newMode.actions = mode.actions.map((element) => {
                if (element === action) {
                    return newAction
                }
                else return element
            })
            return newMode
        }
        else return mode

    })
    //setSpecialModes(newSpecialModes)

}

let headings = specialModes.map((categorgy, index) => {
    return <Heading isActive={categorgy === currentMode ? true : false} onClick={() => categoryOnClick(index)} key={index}>{categorgy.title}</Heading>
})

let actions = currentMode.actions.map((action, index) => {
    return (
        <Action key={index} onClick={() => actionOnClick(action)}>
            <ActionTitle>{action.title}</ActionTitle>
            <ActionValue>{action.value}</ActionValue>
        </Action>
    )
})
return (
    <Wrapper>
        <Category>
            {headings}
        </Category>
        <ActionsWrapper toggleRadiusCorner={currentMode === specialModes[0] ? false : true}>
            {actions}
        </ActionsWrapper>

    </Wrapper>
)

} }

Context.tsx上下文.tsx

interface ContextType {
specialModesContext: {
    specialModes: Array<ISpecialModes>,
    setSpecialModes: React.Dispatch<React.SetStateAction<ISpecialModes[]>>
},
currentModeContext: {
    currentMode: ISpecialModes,
    setCurrentMode: React.Dispatch<React.SetStateAction<ISpecialModes>>
},
inputValueContext: {
    inputValue: string,
    setInputValue: React.Dispatch<React.SetStateAction<string>>
},
inputSuperscriptValueContext: {
    inputSuperscriptValue: string,
    setInputSuperscriptValue: React.Dispatch<React.SetStateAction<string>>
},
performCalc: () => string
}

export const AppContext = createContext({} as ContextType);

export const ContextProvider: FC = ({ children }) => {
const [SpecialModes, setSpecialModes] = useState([
    {
        title: 'Rafter',
        actions: [
            {
                title: 'Span',
                active: false
            },
            {
                title: 'Ridge Thickness',
                active: false
            },
            {
                title: 'Pitch',
                active: false
            }
        ],
    },
    {
        title: 'General',
        actions: [
            {
                title: 'General1',
                active: false
            },
            {
                title: 'General2',
                active: false
            },
            {
                title: 'General3',
                active: false
            }
        ],
    },
    {
        title: 'Stairs',
        actions: [
            {
                title: 'Stairs1',
                active: false
            },
            {
                title: 'Stairs2',
                active: false
            },
            {
                title: 'Stairs3',
                active: false
            }
        ],
    }
] as Array<ISpecialModes>)

const [currentMode, setCurrentMode] = useState(SpecialModes[0])

const [inputValue, setInputValue] = useState('0')
const [inputSuperscriptValue, setInputSuperscriptValue] = useState('')

const replaceCharsWithOperators = (string: string): string => {
    let newString = string.replaceAll(/\s/g, '') // delete white space 
    newString = newString.replace('×', '*')
    newString = newString.replace('÷', '/')
    console.log(string)
    console.log(newString)
    return newString
}

const performCalc = (): string => {
    let originalEquation = `${inputSuperscriptValue} ${inputValue} =`
    let equation = inputSuperscriptValue + inputValue
    let result = ''
    equation = replaceCharsWithOperators(equation)
    result = eval(equation).toString()
    setInputSuperscriptValue(`${originalEquation} ${result}`)
    setInputValue(result)
    console.log(result)
    return result
}

return (
    <AppContext.Provider value={
        {
            specialModesContext: {
                specialModes: SpecialModes,
                setSpecialModes: setSpecialModes
            },
            currentModeContext: {
                currentMode,
                setCurrentMode
            },
            inputValueContext: {
                inputValue,
                setInputValue
            },
            inputSuperscriptValueContext: {
                inputSuperscriptValue,
                setInputSuperscriptValue
            },
            performCalc
        }}>
        {children}
    </AppContext.Provider>
)
}

In your mode.actions.map() function you are indirectly changing actions field of your original specialModes array.在您的mode.actions.map() function 中,您正在间接更改原始specialModes数组的actions字段。

To fix this problem you need to create shallow copy of specialModes array Using the ... ES6 spread operator.要解决此问题,您需要使用... ES6 扩展运算符创建specialModes数组的浅表副本。

const clonedSpecialModes = [...specialModes];
let newSpecialModes = clonedSpecialModes.map((mode) => { 
    // rest of your logic here
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM