繁体   English   中英

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

[英]Context state being updated unexpectedly - React Typescript

第一次发帖,如果需要更多信息,请告诉我。

试图弄清楚为什么我的全局 state 使用上下文 API 正在更新,即使我的 setSate 方法被注释掉。 我想我可能已经意外地直接改变了 state 但我不相信我是

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>
)

}

上下文.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>
)
}

在您的mode.actions.map() function 中,您正在间接更改原始specialModes数组的actions字段。

要解决此问题,您需要使用... 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