What could be the reason for a "Delay" in the state update process within Redux?

I'm currently facing some issues with the Redux and React Native code provided below.

The goal is to build a workout tracking application where users can input their progress. I've implemented a 'workoutSessionSlice' to manage the state.

const initialState: IWorkoutSessionState = {
  currentTrackingEquipment: {
    createdOn: { seconds: 0, nanoseconds: 0 },
    equipmentName: '',
    repetitions: [],
    results: [],
    repetitionIndex: 0,
  },
  hasRunningSession: false,
  isTrackingEquipment: false,
  savedSessionEquipmentRecords: [],
};

export const workoutSessionSlice = createSlice({
  name: 'workoutSession',
  initialState,
  reducers: {
    saveEquipmentRecord: (
      state: any,
      action: PayloadAction<IEquipmentRecord>
    ) => {
      state.savedSessionEquipmentRecords.push(action.payload);
    },
    addResult: (state: any, action: PayloadAction<IRepResult>) => {
      state.currentTrackingEquipment.results[
        state.currentTrackingEquipment.repetitionIndex
      ] = action.payload;
    },
    updateRepIndex: (state: any, action: PayloadAction<number>) => {
      state.currentTrackingEquipment.repetitionIndex = action.payload;
    },
  },
});

The user interacts with the app by using specific equipment and recording their progress for each repetition. However, there seems to be a delay in updating the state, as evidenced by logging the payload and state within a button function:

const handleAddRep = (success: boolean, nextRepIndex: boolean) => {

    console.log({
      repetitions:
        workOutSession.currentTrackingEquipment.results[
          workOutSession.currentTrackingEquipment.repetitionIndex
        ].repetitions,
      weight: equipmentTracking.wheelPickerValue,
      success,
    });

    dispatch(
      addResult({
        repetitions:
          workOutSession.currentTrackingEquipment.results[
            workOutSession.currentTrackingEquipment.repetitionIndex
          ].repetitions,
        weight: equipmentTracking.wheelPickerValue,
        success,
      }),
    );

    console.log(workOutSession);
  };

The issue of delayed state update persists even when attempting to save a record, preventing the last object in the results array from being updated properly.

onPress={() => {
  Alert.alert('Successfully finished rep?', undefined, [
    {
      text: 'Yes',
      onPress: () => {
        if (
          workOutSession.currentTrackingEquipment
            .repetitionIndex ===
          workOutSession.currentTrackingEquipment.results.length - 1
        ) {
          handleAddRep(true, false);  
          Alert.alert('Finished tracking equipment?', undefined, [
            {
              text: 'Yes',
              onPress: () => {
                handleFinishEquipmentTracking(); 
              },
            },
            {
              text: 'No, go back',
            },
          ]);
        } else {
          handleAddRep(true, true);
        }
      },
    },
  ]);
}}

I've attempted strategies like directly modifying values at object keys instead of replacing entire objects, but to no avail. Any assistance would be greatly appreciated!

Solved! Special thanks to Phry.

In order to resolve the issue, modifications were made as follows:

Prior to this change, 'handleFinishEequipmentTracking' was called within the code:

const handleFinishEquipmentTracking = () => {
  dispatch(
    saveEquipmentRecord({
      createdOn: workOutSession.currentTrackingEquipment.createdOn,
      equipmentName: workOutSession.currentTrackingEquipment.equipmentName,
      repetitions: workOutSession.currentTrackingEquipment.repetitions,
      results: workOutSession.currentTrackingEquipment.results,
      repetitionIndex:
        workOutSession.currentTrackingEquipment.repetitionIndex,
    }),
  );
};

The parameter provided in 'saveEquipmentRecord', explained by Phry, is a local variable and does not update when the state changes via 'handleAddRep'. Two simple adjustments were made to address this:

const handleFinishEquipmentTracking = () => {
  dispatch(saveEquipmentRecord());
};

Additionally, in the reducer function, changes were made to ensure that the source of data for saved equipment records comes directly from the state itself rather than a copy stored in a local variable:

Previous approach:

saveEquipmentRecord: (
  state: any,
  action: PayloadAction<IEquipmentRecord>,
) => {
  state.savedSessionEquipmentRecords.push(action.payload);
},

Revised implementation:

saveEquipmentRecord: (state: any) => {
  state.savedSessionEquipmentRecords.push(state.currentTrackinEquipment);
},

Answer №1

Don't be fooled by the appearance of a "delay" - what you're actually seeing is old, stagnant data that will never receive updates.

Consider this scenario:

let state = { foo: 1 }
const s = state
state = { foo: 2 }
// At this point, s remains { foo: 1 } while state becomes { foo: 2 }

Even when your state transitions to a new value (which results in an entirely new object due to immutable updates), your local variables won't automatically reflect this change - they maintain their original values.

When the component undergoes re-rendering in the future,

const something = useSelector(...)
will be re-executed. This creates a fresh variable with the same name that holds the updated value (only to become outdated once again).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to Modify CSS in Angular 6 for Another Element in ngFor Loop Using Renderer2

I have utilized ngFor to add columns to a table. When a user clicks on a <td>, it triggers a Dialog box to open and return certain values. Using Renderer2, I change the background-color of the selected <td>. Now, based on these returned values, ...

Strategies for properly transferring formik props to the {children} component

Seeking assistance from anyone who can help me. I have developed a versatile form component using Formik, which is functioning smoothly except for one unresolved issue. This is my customizable form component export const Form = (props: any) => { c ...

"What is the appropriate TypeScript type for this specific JSX code - React.ReactElement, React.ReactNode, and React.FunctionComponent all prove to be inadequate in this

Having an issue with assigning a type to my prop SubmissionComponent. This prop is expecting JSX, possibly a button or a more complex structure. For example: const SubmissionComponent = <p>hi</p>; which is then used like this: <Submitter ...

Popup appears on incorrect page

As part of my app development project, I implemented a popover feature that opens when clicking on a label. Initially, this functioned smoothly within a tab navigation setup. However, after transitioning from tab modules to the app-routing module to displa ...

Positioning of SVG text along the y-axis

https://i.sstatic.net/FkBRo.png In my project, I am creating a population pyramid using d3 in combination with react. While d3 handles the calculations, react is responsible for rendering the DOM elements. Everything is going smoothly so far, except for p ...

Using JavaScript to round up the number

I need help rounding numbers in a specific way: Value Expected 0,523% 1% 2,235% 2,5% -0,081% -0,5% -1,081% -1,5% How can I achieve this using JavaScript? Possible Solution: static round (num) { const abs = Math.abs(num); const sign = num ...

Classbased Typescript implementation for managing state with a Vuex store

Hey everyone, I'm currently working on a Vue project with Vuex using decorators for strong typing in my template. As someone new to the concept of stores, I am struggling to understand how to properly configure my store to work as expected in my comp ...

Angular2 and Firebase App unable to Compile due to TypeScript Issue

Latest Update: The recent issue causing the app to crash upon launch has been successfully resolved. Interestingly, it was not due to TypeScript compilation errors. In the Git repository's main.ts file, all that was needed was a simple line change: ...

Enforcing TypeScript restrictions on method chaining during object creation

Let's consider this unique sample class: class Unique { public one(): Pick<this, "two" | "three"> { return this; } public two(): Pick<this, "three"> { return this; } public three(): string { ...

What is the method for importing styles in Next.js without including the file extension?

I've got a project set up with Next.js, TypeScript, and SCSS. In every app/*/page.tsx or components/*/page.tsx, there's a line importing the stylesheet like import style from "styles/*/index.module.scss". I find these lines to be too lo ...

TSLint Errors Update: The configuration provided cannot locate implementations for the following rules

After upgrading my tslint to version 4.0.2, I encountered numerous errors like the ones shown below: Could not find implementations for the following rules specified in the configuration: directive-selector-name component-selector-name directi ...

Error in Store.subscribe: TypeError - function (__webpack_require__) is invalid

I recently attempted to incorporate the Redux "subscribe" method into my project to automatically store specific state changes in local storage, following Dan Abramov's guidance in this informative video: Persisting the State to the Local Storage How ...

What are the steps to access a query parameter within an API route.js file using the latest App routing strategy?

Here is the goal I am aiming for: Utilize Next.js with App router. Establish a backend route /api/prompt?search=[search_text] Retrieve and interpret the search query parameter in my route.ts file. Based on the search parameter, send back data to the front ...

Create a tuple in Typescript without explicitly specifying it

Is it possible to create a tuple in Typescript without using type hinting? If I try to simply do const tuple = [1, 2]; the type of tuple becomes number[] The closest I can come to a one-liner is const tuple: [number, number] = [1, 2]; Am I overlooki ...

Creating nested return types: A guide to defining function return types within a Typescript class

My large classes contain functions that return complex objects which I am looking to refactor. class BigClass { ... getReferenceInfo(word: string): { isInReferenceList:boolean, referenceLabels:string[] } { ... } } I am considering somethi ...

AngularJS and TypeScript encountered an error when trying to create a module because of a service issue

I offer a service: module app { export interface IOtherService { doAnotherThing(): string; } export class OtherService implements IOtherService { doAnotherThing() { return "hello."; }; } angular.mo ...

Showing information from asynchronous AsyncStorage.getItems in React Native

In my app, users have to validate their success on challenges by clicking a validation button which saves the "key":"value" pair of the challenge using this function: async function validate(challenge_nb) { try { await AsyncStorage.setItem(challenge_n ...

VSC is throwing a type error, but is it still possible to compile the code?

It seems like after downloading some extensions, I started encountering this issue which was not present before. My files are now displaying errors even though everything should be fine. https://i.sstatic.net/cr7Ef.png The error seems to be related to ca ...

Angular 5 is throwing an error that says: "There is a TypeError and it cannot read the property 'nativeElement' because it

Being aware that I may not be the first to inquire about this issue, I find myself working on an Angular 5 application where I need to programmatically open an accordion. Everything seems to function as expected in stackblitz, but unfortunately, I am enco ...

Potential for object nullification (ts18047) persists even following explicit validation

Why am I receiving the error message 'event.target.files' is possibly 'null' on the highlighted line even though there is a null check on the previous line? I understand that I can use the non-null assertion operator, as shown at the en ...