当前位置: 首页 > 知识库问答 >
问题:

useReducer值未正确更新

严宏旷
2023-03-14

我正在尝试使用useReducer更新组件的状态。我在useEffect中从mongodb获取了一些信息,在那里我调用了我的useReducer dispatch,以便在组件装载后立即设置我的状态。不幸的是,我的状态没有受到影响,我的UI也没有改变。控制台。useffect语句末尾的log语句显示我的状态仍然具有useReducer调用中设置的初始值。有人能告诉我哪里出了问题吗?另外,我计划稍后在useffect中添加到state和依赖项数组中。以前,当我在做这个的时候,我得到了一个无限的useEffect循环,所以现在我有一个空的错误。不过我想更新状态,让我的UI反映更改。另外,下面是包含useEffect调用的功能组件的代码。

编辑:我的玩家对象最初应该是我当前与mongodb一起使用的用户的对象{健康百分比:100,饥饿百分比:100,水合百分比: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};
            } )();
    }
}

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

共有2个答案

暨曾笑
2023-03-14

你只提出一个要求。为什么要将数据拆分为use State和use Reaver?

下面的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;
};
龚安民
2023-03-14

您的useEffect和Reducer代码很好,状态如您所期望的那样更新,这就是上次控制台更新的原因。日志未记录新状态是因为,分派方法不同步,它会导致重新渲染,并在下一次渲染时更新新状态。我认为您的问题是显示状态

 类似资料:
  • 问题内容: 这可能看起来很奇怪。 我已经用Java(在Eclipse中)编写了代码。然后,我对代码进行了一些修改。现在,我正在尝试运行新代码(已修改),但是它仍然为我提供了先前代码的输出。 我在代码中放置了很少的调试点,但是它跳过了一些调试点(尽管它应该在它们处停止)并在某个调试点处停止,但是即使在这里,它也调用了先前代码中存在的方法。位置(尽管我已经对此发表了评论)。从某个地方看来,它仍然在调试

  • 我已经设置了一个谷歌工作表,它附带了一个脚本,运行一个函数来提取chromebook设备信息,除了我感兴趣的两个字段,“cpuStatusReports”和“diskVolumeReports”之外,效果非常好。脚本记录器确实显示了正确的信息,但我的工作表单元格值设置为例如 {cpuUtilizationPercentageInfo=[Ljava.lang.Object;@d151552,cpuT

  • 我有一个django模型,它的id开始奇怪地增加。 列的后缀定义(从詹戈模型生成): 然后我通过django管理员创建了一个新记录: 然后我创建了一个新记录,它跳过了值17224,并插入了主键17225: 有人知道为什么会发生这种情况吗?应用程序此时并不关心,因为id仍在增加,但是在过去的几个新对象中,PKs已经从427跳过-

  • 招呼: 我认为我没有正确更新我的复杂状态: 如何正确更新此状态?谢谢 https://codesandbox.io/s/intelligent-ellis-qi97k?file=/src/App.js

  • 我正在尝试创建一个SNMP4j代理,但发现很难正确理解该过程。我已经成功创建了一个可以使用snmpwalk从命令行查询的代理。我遇到的困难是理解如何更新存储在我实现的MIB中的值。 下面显示了我用于创建MIB的相关代码(我实现了主机资源MIB) 这似乎足以创建可运行的代理。我不明白的是,我应该如何更改MIB中存储的值(例如,如何更改HrSWRunStatus的值)。似乎有一些乱七八糟的方法,但它们

  • 我使用useReducer保存一些状态,如下面的代码所示,但它没有从array reducer函数返回值。 过程: 当我单击屏幕上的按钮时,它会从数据库中获取信息 该信息存储在batchEntries变量中 当批次条目发生更改时,我使用useEffect由雇主触发DispatchEntries 这会导致减速器运行 我知道内部减少函数会运行,因为如果我把它包装在控制台日志中,它会将我期望的数据输出到