0

I have a component called Test that receives 2 props: CurrentPage and OnPageRequest: (currentPage: number) => void

When the parent component uses Test, it sets the Current page number in its state. As you update, the input field below, that value gets fed back up to the parent component via the OnPageRequest as:

OnPageRequest(e.target.value);

wherein return, the parent component updates its current page number in the state.

Test component:

const handlePageNumberBlur = (e) => {
    OnPageRequest(e.target.value);
}

render() {
    return (
        <input
            title="Current Page"
            onBlur={handlePageNumberBlur}
            aria-label="Current Page"
            min="1"
            max={TotalPages}
            placeholder="1"
            type="number"
            value={this.props.CurrentPage} />
    )
}

I'm trying to write Test in such a way so that it only fires back the newly inputted value only when the onBlur event is triggered. But I've learned that with the above code, it never updates the value. It only does it if I have an onChange event where I do: OnPageRequest(e.target.value);

How can I get it to change only when onBlur fires?

SAMPLE: https://codesandbox.io/s/kumuc

blankface
  • 5,757
  • 19
  • 67
  • 114
  • Not sure if that's related but I think this issue can help you with your problem: https://stackoverflow.com/questions/41832389/updating-a-react-input-text-field-with-the-value-on-onblur-event – Thomas Lombart May 27 '19 at 07:02
  • how input value will update if you don't have `onChange` as your input in controlled? and if input value is not updated, your `handlePageNumberBlur` function will receive same value everytime. – Sameer Reza Khan May 27 '19 at 07:04
  • Is it possible to share your code in a code sandbox? – A.K.47 May 27 '19 at 09:51
  • @A.K.47 I've updated the initial post with a sample – blankface May 27 '19 at 11:11

1 Answers1

1

Try using defaultValue instead of value. The defaultValue prop only sets the value to the input on initial render and you won´t need to keep it updated if the value of the prop changes.

<input
    { ... }
    defaultValue={this.prop.CurrentPage}
/>

But this can also be an issue if you set CurrentPage after the input has rendered, which depends on where you get your initial value for the prop.

If you need to keep the input updated after the first render, you can update its value using Refs and the componentDidUpdate lifecycle method.

class TestComponent extends React.Component {
    constructor(props) {
        super(props);
        this.inputRef = React.createRef();
    }

    componentDidUpdate(prevProps) {
        if (this.inputRef.current.value != this.props.CurrentPage) {
            this.inputRef.current.value = this.props.CurrentPage;
        }
    }

    /* ... */

    render() {
        return <input 
            { ... }
            defaultValue={this.props.CurrentPage}
            ref={this.inputRef}
        />
    }
}
Rallen
  • 2,240
  • 20
  • 22
  • This still doesn't update the value if I don't set the onChange – blankface May 27 '19 at 11:22
  • 1
    @ZeroDarkThirty You can´t set `value` and `defaultValue` at the same time. Try removing the `value` prop. – Rallen May 27 '19 at 11:24
  • Okay I've implemented a solution. Would appreciate if you can have a look https://codesandbox.io/s/kumuc – blankface May 27 '19 at 11:35
  • Works as intended. The input can be edited and only on blur there is a console message. – Rallen May 27 '19 at 11:37
  • It looks like even if I take out the `useEffect`, it still functions as intended. Why is that? – blankface May 27 '19 at 11:40
  • That is thanks to the `defaultValue` prop. The `value` prop always overwrites the value of the `input`, that also includes changes by the user. That is why there has to be an `onChange` handler. But with `defaultValue` the `input` manages the value itself, because React only overrides the value of the input on the first render. – Rallen May 27 '19 at 11:48
  • Ah okay. Is that why when I inspect the element, the `value` gets overwritten every time the onBlur fires? Basically, its passing the value up to the parent component that again sets the defaultValue? – blankface May 27 '19 at 12:06
  • No. `defaultValue` only is being set once, even if it is updated. The element just keeps its value because React is not overwriting it as it is the default behaviour when using the `value` prop. I recommend you read up on the thematic of [Controlled Components](https://reactjs.org/docs/forms.html#controlled-components) and [Uncontrolled Components](https://reactjs.org/docs/uncontrolled-components.html). – Rallen May 27 '19 at 12:09