【发布时间】:2020-07-03 10:33:01
【问题描述】:
我正在尝试使用 useReducer 更新组件的状态。我在 useEffect 中从 mongodb 获取一些信息,并在那里调用我的 useReducer 调度,这样我就可以在组件安装后立即设置我的状态。不幸的是,我的状态没有受到影响,我的 UI 也没有改变。我的 useEffect 语句末尾的 console.log 语句显示我的状态仍然具有在 useReducer 调用中设置的初始值。谁能告诉我这里哪里出错了?另外,我计划稍后添加到状态和 useEffect 中的依赖数组。在我处理这个问题之前,我得到了一个无限的 useEffect 循环,所以现在我有一个空错误。不过,我想更新状态并让我的 UI 反映更改。无论如何,这里是包含 useEffect 调用的功能组件的代码。
编辑:my_player 对象最初应该是我当前与 mongodb 一起使用的用户的此对象 {health_percent: 100, hang_percent: 100, hydration_percent: 100}
const change_progress_color = (pet_percentage: any) => {
// change the attribute's color depending on pet_attr value
// PROGRESS_COLORS IS JUST AN ENUM OBJ WITH COLOR CODES
let color;
if (pet_percentage < .10)
color = PROGRESS_COLORS[1];
else if (pet_percentage < .30)
color = PROGRESS_COLORS[2];
else if (pet_percentage < .50)
color = PROGRESS_COLORS[3];
else if (pet_percentage < .75)
color = PROGRESS_COLORS[4];
else if (pet_percentage < .90)
color = PROGRESS_COLORS[5];
else
color = PROGRESS_COLORS[6];
return color;
};
const Player: React.FC = () => {
const [player, setPlayer] = useState<any>();
const [state, dispatch] = useReducer<React.Reducer<State, Actions>>(reducer,
{health: 0, hydration: 0, hunger: 0});
useEffect(() => {
console.log("running useEffect");
(async () => {
var my_player = await getPlayer();
if (my_player)
if (my_player.length > 0) {
const p: any = my_player[0];
setPlayer(p);
console.log("here is my player", p);
dispatch({type: "ChangeHealth", diff: p.health_percent});
dispatch({type: "ChangeHunger", diff: p.hunger_percent});
dispatch({type: "ChangeHydration", diff: p.hydration_percent});
console.log("Here is my state", state);
}
})();
}, []);
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>My Player</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">My Player</IonTitle>
</IonToolbar>
</IonHeader>
<IonList>
<IonItem>
<IonLabel position="floating">
Health
</IonLabel>
<IonProgressBar
value={state.health}
color={change_progress_color(state.health)}/>
</IonItem>
<IonItem>
<IonLabel position="floating">
Hunger
</IonLabel>
<IonProgressBar
value={state.hunger}
color={change_progress_color(state.hunger)}/>
</IonItem>
<IonItem>
<IonLabel position="floating">
Hydration
</IonLabel>
<IonProgressBar
value={state.hydration}
color={change_progress_color(state.hydration)}/>
</IonItem>
</IonList>
</IonContent>
</IonPage>
);
};
export default Player;
这是我在 react 函数之外的代码以及我的类型和 reducer 函数。
type State = {
health: number;
hunger: number;
hydration: number;
};
type ChangeHealth = {
readonly type: "ChangeHealth";
readonly diff: number; // this number is going to need to be divided by 100
}
type ChangeHunger = {
readonly type: "ChangeHunger";
readonly diff: number; // this number is going to need to be divided by 100
}
type ChangeHydration = {
readonly type: "ChangeHydration";
readonly diff: number; // this number is going to need to be divided by 100
}
type Actions = ChangeHealth | ChangeHunger | ChangeHydration;
function reducer(state: State, action: Actions): State {
switch (action.type) {
case "ChangeHealth":
return (() => {
console.log("running func");
console.log("here is the diff ", action.diff);
let new_health = (state.health + action.diff) / 100;
console.log(new_health);
if (new_health > 1)
new_health = 1;
return {...state, health: new_health};
} )();
case "ChangeHunger":
return (() => {
let new_hunger = (state.hunger + action.diff) / 100;
if (new_hunger > 1)
new_hunger = 1;
return {...state, hunger: new_hunger};
} )();
case "ChangeHydration":
return (() => {
let new_hydration = (state.hydration + action.diff) / 100;
if (new_hydration > 1)
new_hydration = 1;
return {...state, hydration: new_hydration};
} )();
}
}
任何帮助将不胜感激。谢谢
【问题讨论】:
-
你能用它的 html 分享整个 Player 组件吗?
-
@AleksandreJavakhishvili 刚刚做到了。谢谢你看我的问题。所以基本上我希望这些值更新,以便我可以在我的 IonProgress 栏中使用它们。根据这些状态值,我也会更改进度条的颜色
-
我还有一个问题,
console.log("here is my player", p);这一行记录了什么? -
@AleksandreJavakhishvili 我用我的玩家 _id、我的用户 id 和以下键健康百分比、饥饿百分比、水合百分比都为 100 取回了一个对象。所以我将值传递给已定义且大于的调度0
-
最后一个console.log在useEffect中打印错误状态的原因是因为dispatch(它不是同步的)方法导致重新渲染,新的状态会在新的渲染中更新
标签: reactjs typescript