Been stuck here for a week and can't find anything that works. Here is my context file:
import { createContext, useState, useEffect } from 'react';
import * as sm from './StatManagement';
import { PlayerMenu, BossHpBar, BossArea, MainPage } from './MainPage';
//used for the boss hp bar
interface BossContextValue {
BossHP: number;
setBossHP: (value: number) => void; // Function that takes a number
}
export const BossContext = createContext<BossContextValue>({
BossHP: sm.boss_stats.hp,
setBossHP: () => { },
});
function ContextManagement() {
const [BossHP, setBossHP] = useState(sm.boss_stats.hp);
useEffect(() => {
//This never triggers
console.log('BossHP updated:', BossHP);
}, [BossHP]);
return (
<BossContext.Provider value={{ BossHP, setBossHP }}>
<PlayerMenu player='' isPlayerTurn={false} />
<BossHpBar />
</BossContext.Provider>
)
}
export default ContextManagement;
What I'm trying to do is create a global state for BossHP. It should update when this button is clicked:
export const PlayerMenu: React.FC<PlayerMenuProps> = ({ player, isPlayerTurn }) => {
const { setBossHP } = useContext(BossContext);
//other elements
<div className=' grid grid-cols-2 grid-rows-2'>
{current_attacks.map(
(attack, index) =>
<li key={index} className='atk-btn'>
<button onClick={() => {
const new_hp = pa.PlayerAttack(attack);
setIsAttackAreaShown(true);
setCurrentAttack(attack);
setBossHP(new_hp);
}}>
//unrelated
}
Then it should update the progress bar here. This component is only linked to PlayerMenu through the context.
export const BossHpBar = () => {
const { BossHP } = useContext(BossContext);
useEffect(() => {
//doesn't update
console.log('BossHP updated:', BossHP);
}, [BossHP]);
console.log("boss hp bar rendered" + BossHP)
return (
<progress className={
'block h-8 glow-ani-border-black boss-prog w-10/12'
} value={BossHP} max={sm.boss_stats.max_hp}></progress>
)
}
I created a simple working example based on your code, so when you click the button - the variable in the progress bar is updating. You can check an example in playground here
import React, { createContext, useState, useContext, useEffect } from 'react';
const sm = {
boss_stats: {
hp: 100,
max_hp: 200,
},
};
interface PlayerMenuProps {
player: string;
isPlayerTurn: boolean;
}
export const BossContext = createContext<{
BossHP: number;
setBossHP: (value: number) => void;
}>({
BossHP: sm.boss_stats.hp,
setBossHP: () => {},
});
const PlayerMenu: React.FC<PlayerMenuProps> = ({ player, isPlayerTurn }) => {
const { setBossHP } = useContext(BossContext);
const handleAttack = () => {
const new_hp = Math.max(0, Math.floor(Math.random() * 100));
setBossHP(new_hp);
};
return (
<div>
<button onClick={handleAttack}>Attack</button>
</div>
);
};
const BossHpBar = () => {
const { BossHP } = useContext(BossContext);
return (
<div>
<h2>Boss HP: {BossHP}</h2>
<progress value={BossHP} max={sm.boss_stats.max_hp}></progress>
</div>
);
};
const ContextManagement = () => {
const [BossHP, setBossHP] = useState(sm.boss_stats.hp);
useEffect(() => {
console.log('BossHP updated:', BossHP);
}, [BossHP]);
return (
<BossContext.Provider value={{ BossHP, setBossHP }}>
<PlayerMenu player="" isPlayerTurn={false} />
<BossHpBar />
</BossContext.Provider>
);
};
export default function App() {
return <ContextManagement />;
}