React state doesn't get set when settings two states consecutively

Asked
Active3 hr before
Viewed126 times

9 Answers

doesnsettingsstatesconsecutivelystatereact
90%

Try searching for similar questions,Connect and share knowledge within a single location that is structured and easy to search., Toggling between an image grid and image slider with one array of images in react hooks

 Pretag team - issue, fix, solve, resolve
88%

const {useState, useEffect} = React;

function App() {
  const [userRequest, setUserRequest] = useState({
    loading: false,
    user: null,
  });

  useEffect(() => {
    // Note that this replaces the entire object and deletes user key!
    setUserRequest({ loading: true });
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        setUserRequest({
          loading: false,
          user: data.results[0],
        });
      });
  }, []);

  const { loading, user } = userRequest;

  return (
    <div>
      {loading && 'Loading...'}
      {user && user.name.first}
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
load more v
72%

To recap: Using setState, we can update a component's state. We frequently use events to trigger these updates. setState is called asynchronously and merges the existing state with whatever object is passed in. We can also pass a function to setState, which allows us to write state changes that are based on the existing state values.,It's important to note the difference between changes in state and changes in props. Changes in state and/or props will both trigger a re-render of our React component. However, changes in state can only happen internally due to components changing their own state. Thus, a component can trigger changes in its own state.,A component cannot change its props. Changes in props can only happen externally, meaning the parent or grandparent component changes the values it passing down to its children.

For example, let's say we have a component with a button, and a bit of text to indicate whether that button has been pressed yet:

// src/components/ClickityClick.js
import React from "react";

class ClickityClick extends React.Component {
  constructor() {
    super();

    // Define the initial state:
    this.state = {
      hasBeenClicked: false,
    };
  }

  handleClick = () => {
    // Update our state here...
  };

  render() {
    return (
      <div>
        <p>I have {this.state.hasBeenClicked ? null : "not"} been clicked!</p>
        <button onClick={this.handleClick}>Click me!</button>
      </div>
    );
  }
}

export default ClickityClick;

// src/index.js
import React from "react";
import ReactDOM from "react-dom";

import ClickityClick from "./components/ClickityClick";

ReactDOM.render(<ClickityClick />, document.getElementById("root"));
load more v
65%

Passing Functions to Components,Pass a function instead of an object to setState to ensure the call always uses the most updated version of state (see below). ,props (short for “properties”) and state are both plain JavaScript objects. While both hold information that influences the output of render, they are different in one important way: props get passed to the component (similar to function parameters) whereas state is managed within the component (similar to variables declared within a function).

incrementCount() {
   // Note: this will *not* work as intended.
   this.setState({
      count: this.state.count + 1
   });
}

handleSomething() {
   // Let's say `this.state.count` starts at 0.
   this.incrementCount();
   this.incrementCount();
   this.incrementCount();
   // When React re-renders the component, `this.state.count` will be 1, but you expected 3.

   // This is because `incrementCount()` function above reads from `this.state.count`,
   // but React doesn't update `this.state.count` until the component is re-rendered.
   // So `incrementCount()` ends up reading `this.state.count` as 0 every time, and sets it to 1.

   // The fix is described below!
}
load more v
75%

Next, we’ll make the Clock set up its own timer and update itself every second.,This page introduces the concept of state and lifecycle in a React component. You can find a detailed component API reference here.,In this section, we will learn how to make the Clock component truly reusable and encapsulated. It will set up its own timer and update itself every second.

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(    element,    document.getElementById('root')  );}

setInterval(tick, 1000);
load more v
40%

Consider the following line of code. When you read it, the intentions are clear: set foo to 42 and keep the other properties untouched. But the change may never take effect if somebody else calls setState during the same update cycle and sets a different property!,These state changes must be done atomically and you must be sure that you are basing your decisions and actions on the current view of the state.,But there are far less obvious situations which lead to multiple calls to setState. For example: combination of componentWillReceiveProps and an input onChange event handler, like I had in my application.

Consider the following line of code. When you read it, the intentions are clear: set foo to 42 and keep the other properties untouched. But the change may never take effect if somebody else calls setState during the same update cycle and sets a different property!

this.setState({
   ...this.state,
   foo: 42
});
load more v
22%

I think the confusing part here is that you’re both setting the state and want to set a timeout based on that state (and in the timeout, set the state again).,reading this.state before the first setState() call in the event handler will give you the current state.,It seems in this case the prevState you receive in the functional setState is not always the state rendered on the UI

this.setState({
   counter: 1
});
this.setState((prevState, props) => ({
   console.log(prevState.counter)
}));
this.setState({
   counter: 2
});
this.setState((prevState, props) => ({
   console.log(prevState.counter)
}));
load more v
60%

Use the verbose version of the state variable's set function. This was the avenue I pursued for a while. But it can get, well... ugly. Consider this: ,Could this also be solved by just making the validations also async?,So, run validation each time you render, or if it's heavyweight, then use useMemo. If you can break down validation into smaller parts, each one in it's useMemo, then some can be skipped if their input (field value, or the result of another validation step) hasn't changed.

export default function App() {
  const [memberId, setMemberId] = useState('');
  const [validateEntireForm, setValidateEntireForm] = useState(false);

  const updateMemberId = userValue => {
    setMemberId(userValue);
    validateMemberId();
    if (validateEntireForm)
      validateForm();
  }

  const validateForm = () => {
    if (!validateEntireForm)
      setValidateEntireForm(true);
    validateMemberId();
    // validate the rest of the fields in the form  
  }

  const validateMemberId = () => {
    // validate based on the CURRENT value of 'memberId'
    return validOrNot;
  }

  return (<>UX Here...</>);
}
load more v
48%

Principles of using selector functions to derive data and encapsulate lookups,Why good Redux architecture keeps state minimal and derives additional data,The first reason to use selector functions is for encapsulation and reusability when dealing with your Redux state shape.

function TodoList() {
   const [todos, setTodos] = useState([])
   // Derive the data while rendering  const allTodosCompleted = todos.every(todo => todo.completed)
   // render with this value}
load more v

Other "doesn-settings" queries related to "React state doesn't get set when settings two states consecutively"