Replicate the functionality of the second parameter of setState within a useState setup, allowing for actions to be taken after the state has been

In the previous version of React, we were able to execute code after the state has changed by using this method:

setState( prevState => {myval: !prevState.myval}, () => {
    console.log("myval is changed now");
)

One way to achieve something similar in the current version is by using React.useEffect:

const [myval, setMyval] = React.useState(false);
React.useEffect(() => {
    console.log("myval is changed now");
}

//somewhere
setMyval(o => !o);

However, in some cases like mine, determining which action needs to happen after the state change depends on where it occurred originally:

//somewhere
setState( prevState => {myval: !prevState.myval}, () => {
    console.log("myval is changed now");
)
//somewhere else 
setState( prevState => {myval: !prevState.myval}, () => {
    console.log("myval has changed somewhere else");
)

Converting these to useState + setMyval would cause the same effect to fire at both positions, making it difficult to determine the required action using useEffect.

How can I achieve the above functionality in a hook-based function component?


A better scenario would be a screen with two buttons: one for loading previous data and another for loading next data. The buttons should be disabled while the isLoading state is true. To ensure only one load operation happens, we need to prevent a race condition that might occur due to asynchronous state changes.

Using a callback upon changing the state can help prevent this race condition and ensure that only one load operation occurs:

class SomScreen extends React.component {
    state = { isLoading: false }
    render() {
        <div>
            <button 
                disabled={this.state.isLoading} 
                onclick={(e) => {
                    if (!this.state.isLoading) {
                            this.setState((p) => ({isLoading: true}), () => {
                            await fetchPreviousDataAndDoSomethingWithIt()
                            setState({isLoading: false});
                        });
                    }
                }
            />Previous</button>
            <button 
                disabled={this.state.isLoading} 
                onclick={(e) => {
                    if (!this.state.isLoading) {
                        this.setState((p) => ({isLoading: true}), () => {
                            await fetchNextDataAndDoSomethingWithIt()
                            setState({isLoading: false});
                        });
                    }
                }
            />Next</button>
        </div>
    }
}

Answer №1

To determine if an asynchronous action is currently in progress, you can create a custom hook that checks each individual asynchronous action and computes the overall loading state. This approach involves modeling each asynchronous action separately and then calculating the isLoading status. Here's an example of how you could implement such a custom hook:

function useAsyncAction(asyncAction) {
  const [isLoading, setIsLoading] = useState(false);
  const callAsyncAction = useCallback(async () => {
    setIsLoading(true);
    await asyncAction();
    setIsLoading(false);
  }, []);
  return [
    isLoading,
    callAsyncAction,
  ]
}

//

function SomScreen() {
  const [asyncAIsLoading, callAsyncA] =
    useAsyncAction(fetchPreviousDataAndDoSomethingWithIt);
  const [asyncBIsLoading, callAsyncB] =
    useAsyncAction(fetchNextDataAndDoSomethingWithIt);
  const isLoading = asyncAIsLoading || asyncBIsLoading

  ...
}

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

Mental stability groq fails to provide the requested information

Having difficulty using Groq to fetch data. All other Groq queries work fine, except this one. When manually setting the $slug variable, the data I'm trying to query works with the Sanity Groq VS plugin but returns undefined in my web app. Query: exp ...

Dynamic TextField sizing

I am currently facing an issue while displaying data on a webpage using TextField component from @material-ui. Each record of data has varying lengths, making most values appear unattractive (occupying only 10% of the textfield width). Even though I am ut ...

Toggle the visibility of a dropdown menu based on the checkbox being checked or unchecked

One challenge I am facing involves displaying and hiding DropDown/Select fields based on the state of a Checkbox. When the checkbox is checked, the Dropdown should be visible, and when unchecked, it should hide. Below is the code snippet for this component ...

What could be causing a react element to fail to update?

I'm currently working on a React component that interacts with a MaterialUi text form. The component utilizes a useState hook to update based on the input received. My goal is to have another variable update when the form is submitted, which will be d ...

Developing React components with Typescript requires careful consideration when defining component props, especially when the component may be

Consider the following scenario: { this.props.userName && <UserProfile userName={this.props.userName} /> In the UserProfile component: interface UserProfileProps { userName: string; } class UserProfile extends React.Component<UserProfile ...

One project contains a pair of React instances

I am currently working on a React Web App and recently encountered an issue with an 'invalid hook call' error. Upon further investigation, I discovered that there are duplicate copies of the React library in my project, including within the CSS f ...

The type 'undefined' cannot be assigned to type 'Element or null'

One of the components I am using looks like this: const data: any[] = [] <Tiers data={data}/> This is how my component is structured: const Tiers = ({ data, }: { data?: any; }) => { console.log('data', data?.length!); ...

Discovering the magic of nesting maps in React-Native without the need for

I am currently developing a react-native app that retrieves its data through an API. I am working on implementing a new feature where the information is grouped by date. The JSON data structure sent by the API looks like this: { "channel_count" ...

What steps should I take to update my react dependencies following an upgrade to react v16?

Ever since I upgraded to react v16, I've been encountering warnings from other dependencies when using yarn: warning "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5624333735227b353e3724223c257b64166478677866">[email& ...

Having trouble getting the Popover to show up in the right spot within the Dialog

I'm facing an issue with a Dialog and a ListItem where clicking on the item should trigger edit mode by displaying a Popover. The setup worked fine in an older version of MUI using a Modal, but upon updating to the latest version, the functionality br ...

Creating basic animations using React and GSAP

I’ve been grappling with this issue for days and struggling to comprehend the various sources of documentation and examples available. I'm really hoping someone can assist me with a specific example that I’m currently working on, which might help ...

Error: Unable to access the 'map' property of undefined in React while trying to read this.props.rsl['data']

The problem I am encountering is related to the map function, which displays data in the console log console.log("iiiiiiiiii",this.props.rsl['data']). However, when I attempt to use the map function {this.props.rsl['data'].map(row=>{ ...

Converting React to Typescript and refactoring it leads to an issue where the property 'readOnly' is not recognized on the type 'IntrinsicAttributes & InputProps & { children?: ReactNode; }'

I'm currently in the process of refactoring an application using Typescript. Everything is going smoothly except for one particular component. I am utilizing the Input component from the library material-ui. import {Input} from "material-ui"; class ...

retrieving information from GraphQL for use in React applications

After cloning this React dashboard and modifying it to suit my requirements, I wanted to retrieve data from graphql and present it in a table (including orders and products tables). Specifically discussing the orders section, when a user clicks on a button ...

Extract string data from JSON payload

How can I extract the itemlocation from itemInfo and display it in a new column in my react table using Material UI? While I know this can be done on the backend, I am looking for a way to achieve this without backend involvement. Below is an example of ho ...

Validation errors in the realm of Zod

Below is my code using Next.js 14 with TypeScript, React Hook Form, and Zod for validation. The issue arises when trying to display an error message for an empty form: import React from "react"; import category from "@/components/expenses/ca ...

The React hook useState is struggling to accurately map array objects

Recently, I encountered an issue with a form that sends an array of objects to another React Functional Component: import React, { useState } from 'react' import uuid from 'uuid/v1'; const NewMovieForm = ( {addMovie }) => ...

Tips for updating the selected date format in a Material Table component using React

In the context of using a material table in React, the columns set up are as follows: columns={[ { title: 'Name', field: 'name', type: 'string', }, ...

Develop a cutting-edge front end for Hyperledger Fabric 2.2 with React js and enhance it with a node

Currently, I have developed a unique hyperledger fabric 2.2 blockchain network using javascript and am looking to integrate it with a React.js front end utilizing the node.js API. Despite my efforts to find relevant examples, most resources focus on hyperl ...

Creating a web application using Aframe and NextJs with typescript without the use of tags

I'm still trying to wrap my head around Aframe. I managed to load it, but I'm having trouble using the tags I want, such as and I can't figure out how to load a model with an Entity or make it animate. Something must be off in my approach. ...