我正在尝试使用useReducer更新组件的状态。我从useEffect中的mongodb获取了一些信息,在那里我调用了我的useReducer调度,这样我就可以在组件安装后立即设置我的状态。不幸的是,我的状态没有受到影响,我的UI也没有改变。useEffect语句末尾的console.log语句显示,我的状态仍然是在useReducer调用中设置初始值。有人能告诉我我哪里错了吗?另外,我计划稍后添加到状态和useEffect中的依赖项数组中。之前我在做这个的时候,我得到了一个无限的useEffect循环,所以现在我有一个空错误。不过,我希望更新状态,并让我的UI反映这些更改。下面是包含useEffect调用的函数组件的代码。
编辑: my_player对象最初应该是我当前在mongodb中使用的用户的这个对象{health_percent: 100,hunger_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};
} )();
}
}任何帮助都将不胜感激。谢谢
发布于 2020-03-23 07:03:48
你的useEffect和Reducer代码很好,状态按照你的预期更新了,最后一个console.log没有记录新状态的原因是,调度方法不同步,它会导致重新渲染,并在下一次渲染时更新新状态。我认为您的问题是显示状态<IonProgressBar value={state.hydration} color={change_progress_color(state.hydration)}/>。
发布于 2020-03-23 06:58:50
你只做了一个请求。您将数据拆分到useState和useReduce的原因是什么?
下面的MB代码可以帮助你。
import React, { useEffect, useState } from 'react';
const Player: React.FC = () => {
const [player, setPlayer] = useState({
health: 0,
hydration: 0,
hunger: 0,
});
useEffect(() => {
getPlayer()
.then((response) => {
const [player] = response;
if (player) {
setPlayer((prevState) => {
const health = (prevState.health + player.health_percent) / 100;
const hunger = (prevState.hunger + player.hunger_percent) / 100;
const hydration = (prevState.hydration + player.hydration_percent) / 100;
return ({
health: health > 1 ? 1 : health,
hunger: hunger > 1 ? 1 : hunger,
hydration: hydration > 1 ? 1 : hydration,
});
});
}
})
.catch(({ message }) => {
console.error(message);
});
}, []);
return null;
};
https://stackoverflow.com/questions/60805485
复制相似问题