jondiur
jondiur

Reputation: 3

React update state after updating a different one in useEffect

I need to update my state after updating / setting a different state in my useEffect hook. So far it does not work. What am I doing wrong here?

The isDisabled logic depends on the values of the other states.

const OffersDialogueButton = ({
  type,
  status,
}) => {
  const { invitationType, status: cardStatus } = useJobPositionsContext();
  const { jobPosition } = useJobDetailContext();
  const [dialogStatus, setDialogStatus] = useState<CardStatus>();
  const [dialogType, setDialogType] = useState<CardType>();
  const [color, setColor] = useState<string>();
  const [isDisabled, setIsDisabled] = useState(false);

  useEffect(() => {
    setDialogStatus(status || cardStatus);
    setDialogType(type || invitationType || 'default');
    setIsDisabled(
      (dialogType === 'invitation' && dialogStatus !== 'pending') || (dialogType === 'application' && cardStatus !== 'accepted'),
    );
    setColor(BUTTON_VARIANT_BY_STATUS[dialogStatus]);
  }, [type, status, isDisabled]);

Upvotes: 0

Views: 87

Answers (3)

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18113

When computing isDisabled and color state variables, you must use the new values of dialogStatus and dialogType.

const OffersDialogueButton = ({type, status}) => {
  const { invitationType, status: cardStatus } = useJobPositionsContext();
  const { jobPosition } = useJobDetailContext();
  const [dialogStatus, setDialogStatus] = useState<CardStatus>();
  const [dialogType, setDialogType] = useState<CardType>();
  const [color, setColor] = useState<string>();
  const [isDisabled, setIsDisabled] = useState(false);

  useEffect(() => {
    const nextDialogStatus = status || cardStatus;
    const nextDialogType = type || invitationType || 'default';
    const nextIsDisabled = 
      (nextDialogType === 'invitation' && nextDialogStatus !== 'pending') || 
      (nextDialogType === 'application' && cardStatus !== 'accepted');
    const nextColor = BUTTON_VARIANT_BY_STATUS[nextDialogStatus];

    setDialogStatus(nextDialogStatus);
    setDialogType(nextDialogType);
    setIsDisabled(nextIsDisabled);
    setColor(nextColor);
  }, [status, cardStatus, type, invitationType]);

Upvotes: 0

Hakob Sargsyan
Hakob Sargsyan

Reputation: 1414

As I understand you want to make setIsDisabled by setDialogType , you need to use other useEffect

React.useEffect(() => {
    setIsDisabled(
      (dialogType === 'invitation' && dialogStatus !== 'pending') || (dialogType === 'application' && cardStatus !== 'accepted'),
    );
  }, [dialogType])

setDialogType is asynchronous , you can not access it immediately after the setState.

Read more about React state here State

Upvotes: 1

grekier
grekier

Reputation: 3696

dialogType and dialogStatus are set in the same function with state set which is async so you cannot expect them to be set when you check them in the same function. You should have a new useEffect for those variables or have a local variable for the checks.

Upvotes: 1

Related Questions