У меня возникла проблема с контекстом React. Я пытаюсь использовать setState, но значение состояния остается неопределенным.
Контекст.js
import {
createContext,
useContext,
useMemo,
useState,
useEffect
} from "react";
const PlayerGamepadContext = createContext();
export const PlayerGamepadProvider = ({
...props
}) => {
const [gamepads, setGamepads] = useState([])
const [gamepadsCount, setGamepadsCount] = useState(0)
const [mappedGamepads, setMappedGamepads] = useState([])
// Triggered when button state change
// (button: string, isPressed: bool, controllerIndex: integer) => void
const [onButtonStateChanged, setOnButtonStateChanged] = useState(undefined)
useEffect(() => {
console.info("STATE CHANGED")
console.info(setOnButtonStateChanged);
console.info(onButtonStateChanged); // This shouldn't be undefined after I call "setOnButtonStateChanged"
}, [onButtonStateChanged])
const value = useMemo(() => {
return {
gamepads,
mappedGamepads,
playerCount: mappedGamepads?.length,
setOnButtonStateChanged,
setOnGamepadConnected
}
}, [
gamepads,
mappedGamepads,
setOnButtonStateChanged,
setOnGamepadConnected
])
if (typeof window === 'undefined') {
return "Loading";
}
return <PlayerGamepadContext.Provider value = {value} {...props} />
}
export const usePlayerGamepads = () => {
const context = useContext(PlayerGamepadContext)
return context
}
Компонент.jsx
import React, { useEffect } from 'react'
import { usePlayerGamepads } from '@/components/Context/PlayerGamepadContext'
const TestController = props => {
const [state, setState] = React.useState(undefined)
const [init, setInit] = React.useState(false)
const playerGamepads = usePlayerGamepads()
const handleChangeEvent = (button, isPressed, index) => {
console.info(button, isPressed, index);
};
useEffect(() => {
setState(playerGamepads)
if (playerGamepads && !init) {
setInit(true)
console.info("CALL SET STATE");
playerGamepads.setOnButtonStateChanged(handleChangeEvent)
}
}, [playerGamepads]);
return (
<div></div>
)
}
export default TestController
А вот вывод консоли
1- CALL SET STATE
2- undefined undefined undefined
3- STATE CHANGED
4- ƒ dispatchSetState(fiber, queue, action) {........
5- undefined
Я немного запутался, почему моя функция handleChangeEvent вызывается после использования setOnButtonStateChanged
(строка вывода 2)
но что более важно, почему onButtonStateChanged
все еще не определено после его изменения?
Я попытался передать функцию через реквизит PlayerGamepadProvider, и это сработало, но мне нужно иметь возможность установить ее из состояния.
Я также пытался присвоить onButtonStateChanged
значение по умолчанию.
const [onButtonStateChanged, setOnButtonStateChanged] = useState(console.info)
но вместо этого он напрямую принимает неопределенное значение
Заранее спасибо за помощь
Вы должны обернуть свой корень с помощью <PlayerGamepadContext.Provider value = {value} /> вместо return <PlayerGamepadContext.Provider value = {value} {...props} /> из Context.js
Вы устанавливаете результат handleChangeEvent
как OnButtonStateChanged
, поэтому вызывается журнал консоли, а результат не определен.
Вместо:
playerGamepads.setOnButtonStateChanged(handleChangeEvent)
Пытаться:
playerGamepads.setOnButtonStateChanged(() => handleChangeEvent)
@Maxime, если вы хотите знать, почему, ознакомьтесь с этим часто задаваемым вопросом в документации по реакции.
Пожалуйста, сделайте codeandbox и поделитесь воспроизводимым примером