Setting the defultValue of TextField component of Material UI in React

Wai Yan Hein picture Wai Yan Hein · Jul 31, 2018 · Viewed 8.2k times · Source

I am developing a React JS application. What I am doing now is I am fetching data asynchronously from the server and render the values in the TextField. I know how to do it and my approach is working as well. But, I just do not like my current approach.

This is the working approach

class TestComponent extends React.Component {

    constructor(props)
    {
        super(props);
        this.fetchName = this.fetchName.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.state = {
            name : ''
        }
    }


    fetchName()
    {
        //get the name asynchronously from the server. I am using Axios
        this.setState({ name : nameValueFromTheServer })
    }


    handleChange(e)
    {
        this.setState({ name : e.target.value })
    }

    render()
    {
        return (
            <MuiThemeProvider>
            <div>
                <TextField onChange={this.handleChange} label="Name" value={this.state.name} />
            </div>
            </MuiThemeProvider>
        )
    }
}

The thing I do not like about above approach is that I have to implement handleChange method to retrieve the value of the input value. If I do not implement it, I cannot change the name input value because the state value is not changed. To retrieve a simple input value, I have to write extra lines of code. In jQuery, I just retrieve the input value like this, $(selector).val(). Without implementing the handleChange method, I can use the ref like this.

<TextField inputRedf={(input) => this.tfName = input } label="Name" />

Then I retrieve the value dynamically like this.

this.tfName.value

The problem with using the reference is setting the default value which is fetched asynchronously from the server.

I can set the default value like this to the TextField

<TextField inputRedf={(input) => this.tfName = input } defaultValue={this.state.name} label="Name" />

Pay attention to the defaultValue attribute in the above code. When I set the value using defaultValue, the initial value of the name state will be set to the text field. But we can still change the input value of the name typing in from the UI even if we do not implement the handleChange event. But the problem is that I am getting the data asynchronously and setting the this.state.name dynamically.

So in the component constructor, the name state is empty. Then I set it in the callback of the asynchronous call. But the defaultValue can be set only once. So the input field is always showing empty. What I like to know is, how can I set the defaultValue of the TextField dynamically? The reason I am using ref is that I do not want to implement the onChange event as well to track state the reset the input value. If I could set the defaultValue dynamically, I will just the value dynamically in the callback of the asynchronous call. What is the best solution to simplify this scenario?

Answer

Olim Saidov picture Olim Saidov · Jul 31, 2018

You don't need default value actually. If you want to avoid using onChange handler you can imperatively set input value in async callback:

class TestComponent extends React.Component {
    constructor(props) {
        super(props);
        this.fetchName = this.fetchName.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    fetchName() {
        if(this.tfName.value == '') {
            // only update if user have not changed the input value. 
            this.tfName.value = nameValueFromTheServer; 
        }
    }
    render() {
        return (
            <MuiThemeProvider>
                <div>
                    <TextField 
                        inputRef={(input) => this.tfName = input }
                        label="Name"/>
                </div>
            </MuiThemeProvider>
        );
    }
}