首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >useReducer值未正确更新

useReducer值未正确更新
EN

Stack Overflow用户
提问于 2020-03-23 06:03:06
回答 2查看 325关注 0票数 0

我正在尝试使用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}

代码语言:javascript
复制
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函数。

代码语言:javascript
复制
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};
            } )();
    }
}

任何帮助都将不胜感激。谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-23 07:03:48

你的useEffect和Reducer代码很好,状态按照你的预期更新了,最后一个console.log没有记录新状态的原因是,调度方法不同步,它会导致重新渲染,并在下一次渲染时更新新状态。我认为您的问题是显示状态<IonProgressBar value={state.hydration} color={change_progress_color(state.hydration)}/>

票数 1
EN

Stack Overflow用户

发布于 2020-03-23 06:58:50

你只做了一个请求。您将数据拆分到useState和useReduce的原因是什么?

下面的MB代码可以帮助你。

代码语言:javascript
复制
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;
};

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60805485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档