2

I have a form that uses custom <Input> elements. In the Input component I manage the state of the input (valid/invalid). In the form I ask the user to re-enter the password and I would like that if the user enter both of the password correctly and then modify the first, the second becomes invalid (gets a red background-color).

So in the Form component I want to trigger a reevaluation of the second password Input, every time the value of the first password changes.

In the Form I have the value of the first password stored in a useReducer state, and I thought that passing it in the props of a component would automatically trigger a reevaluation, but that's not the case.

Password
[*****_____]

Re-enter Password
[*****_____]  // "valid" because it has the same value of the first password



...then the user modify the first password:

Password
[********__]

Re-enter Password
[*****_____]  // this component should be reevaluated and set itself to "invalid"

I pass the value of the first password in the props of the second component here:

<Input
    ...props...
    testingFunction={password => password && password === formState.password.value}
/>

I also tried to pass the value more explicitly by adding this property: dependencies={formState.password.value}, but it doesn't work either.

So what's wrong with this approach and what would be a good way to force a reevaluation of the second password component?

anotherOne
  • 1,513
  • 11
  • 20

1 Answers1

1

You can use useEffect to run your re-evaluation in your Input component.

E.g.

import React, { useEffect } from "react";

interface IInputProps extends HTMLInputElement {
  reevaluate?: string;
}

const Input: React.FC<IInputProps> = (props: IInputProps) => {
  useEffect(() => {
    console.log("Run your evaluation code here - This code block will be run whenever `reevaluate` prop is changed");
  }, [props.reevaluate])

  return (
    <input type="text" />
  );
};
choz
  • 17,242
  • 4
  • 53
  • 73
  • Are you telling me that the component by default sees its props changing and doesn't give a damn, but you can make the props trigger actions with an `useEffect` inside of the component? – anotherOne May 29 '21 at 11:20
  • 1
    I tried it and it works! thank you very much! – anotherOne May 29 '21 at 11:55
  • 1
    @SheikYerbouti To answer your first q - Yes, it doesn't give a damn after the initial render. A re-render is performed when the state's changed (not props) - But, it's tricky to tell at first if you pass parent's state to child's props, because it was the parent who was re-rendering. – choz May 30 '21 at 03:13
  • Yeah that's right, the parent component was re-rendering. So wasn't the child component supposed to be re-rendered as well, at least since its props changed? I think that in React you need to use useCallback and React.memo() to prevent the child re-evaluation. So I suspect that my problem was due to Next.js automatically optimizing the code – anotherOne May 31 '21 at 09:32
  • @SheikYerbouti When parent re-renders, then the child should too. – choz May 31 '21 at 13:36
  • So since the parent state was changing (formstate.password.value), the parent was re-rendering and the child should have been automatically re-evaluated, without the need of `useEffect`. However for some reason I need the `useEffect`. If I remove it, the child is not re-evaluated. It must be Next.js doing some optimization. – anotherOne May 31 '21 at 14:51
  • @SheikYerbouti I believe what you're seeing is not Next.js related, rather than how React works. It is **true** that when parent re-renders, children do too. However, [the children's DOM may not get updated](https://stackoverflow.com/a/61898908/1627271). If I understand correctly, you were trying to pass the data to the child via `props`. However, `props` acts as child's state only at initial render. And when the parent's state changes, the children's state **does not**. Have a look at [this answer](https://stackoverflow.com/a/41233828/1627271), and see if it may help. – choz May 31 '21 at 15:08
  • I don't use the props to set the initial state, but I use them to dispatch a new state. If I log the Input's state after having removed useEffect, the state of the second password doesn't change when the first password is modified from matching to being different (and vice versa). So it's not just the actual DOM not being updated. Maybe I should post another question providing my code and asking why I need the useEffect. – anotherOne May 31 '21 at 16:14