英文:
React context will not update (Typescript)
问题
以下是您提供的代码的翻译:
已经卡在这里一周了,找不到任何有效的解决方法。
这是我的上下文文件:
import { createContext, useState, useEffect } from 'react';
import * as sm from './StatManagement';
import { PlayerMenu, BossHpBar, BossArea, MainPage } from './MainPage';
// 用于 Boss 血条
接口 BossContextValue {
BossHP: 数字;
setBossHP: (value: number) => void; // 接受数字的函数
}
出口 const BossContext = createContext<BossContextValue>({
BossHP: sm.boss_stats.hp,
setBossHP: () => { },
});
函数 ContextManagement() {
const [BossHP, setBossHP] = useState(sm.boss_stats.hp);
useEffect(() => {
// 这个永远不会触发
console.log('BossHP 更新:', BossHP);
}, [BossHP]);
返回 (
<BossContext.Provider value={{ BossHP, setBossHP }}>
<PlayerMenu player='' isPlayerTurn={false} />
<BossHpBar />
</BossContext.Provider>
)
}
默认出口 ContextManagement;
我试图做的是创建一个全局状态来存储 BossHP。当点击此按钮时它应该更新:
出口 const PlayerMenu: React.FC<PlayerMenuProps> = ({ player, isPlayerTurn }) => {
const { setBossHP } = useContext(BossContext);
// 其他元素
<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);
}}>
// 无关的内容
}
</li>
)}
</div>
}
然后它 *应该* 在这里更新进度条。这个组件只通过上下文与 PlayerMenu 相关联:
出口 const BossHpBar = () => {
const { BossHP } = useContext(BossContext);
useEffect(() => {
// 不会更新
console.log('BossHP 更新:', BossHP);
}, [BossHP]);
console.log("boss 血条已渲染" + BossHP)
返回 (
<progress className={
'block h-8 glow-ani-border-black boss-prog w-10/12'
} value={BossHP} max={sm.boss_stats.max_hp}></progress>
)
}
请注意,这只是您提供的代码的翻译,没有附加内容。如果您需要任何其他帮助,请告诉我。
英文:
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>
)
}
答案1
得分: 1
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 />;
}
英文:
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
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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 />;
}
<!-- end snippet -->
答案2
得分: 0
你需要在导入时在文件名后面添加文件扩展名,像这样:
import { createContext, useState, useEffect } from 'react.js';
import * as sm from './StatManagement.js';
import { PlayerMenu, BossHpBar, BossArea, MainPage } from './MainPage.js';
// 用于 boss 血量条
interface BossContextValue {
BossHP: number;
setBossHP: (value: number) => void; // 接受一个数字的函数
}
export const BossContext = createContext<BossContextValue>({
BossHP: sm.boss_stats.hp,
setBossHP: () => { },
});
function ContextManagement() {
const [BossHP, setBossHP] = useState(sm.boss_stats.hp);
useEffect(() => {
// 这不会触发
console.log('BossHP 更新:', BossHP);
}, [BossHP]);
return (
<BossContext.Provider value={{ BossHP, setBossHP }}>
<PlayerMenu player='' isPlayerTurn={false} />
<BossHpBar />
</BossContext.Provider>
)
}
export default ContextManagement;
我已经将代码部分翻译好,如有其他需要,请告诉我。
英文:
You Have to add the file extension name after the file name in import. Like this:
import { createContext, useState, useEffect } from 'react.js';
import * as sm from './StatManagement.js';
import { PlayerMenu, BossHpBar, BossArea, MainPage } from './MainPage.js';
//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;
I made as javascript files.
if it is libraries you can replace it with the lib URL. Or use require if it is from npm.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论