0

I've got some confusion with React's setState. I tried to implement changeHandler method to change the state, but i face some problems.

I have created 4 textfields, name property indicates a property of this.state.workerInfo.foo, so inside the changeHandler i extract the event.target.name to link new value with the state.

class EditableWorkerProfile extends Component {
    constructor(props) {
        super(props);
        this.state = {
            pending: false,
            shouldAdd: false,
            worker_id: props.worker._id,
            workerInfo: {
                login: props.worker.login,
                balance: props.worker.balance,
                phoneNum: props.worker.phoneNum.replace(new RegExp("(^\\+7)|(^8)"), "7"),
                birthDate: props.worker.birthDate,
                address: props.worker.address,
                city: props.worker.city,
                name: props.worker.name,
                isDriver: props.worker.isDriver,
                veh_is_open: this.props.worker.isDriver ? this.props.worker.veh_is_open : false,
                veh_height: this.props.worker.isDriver ?  this.props.worker.veh_height : "0",
                veh_width: this.props.worker.isDriver ?  this.props.worker.veh_width : "0",
                veh_length: this.props.worker.isDriver ?  this.props.worker.veh_length : "0",
                veh_loadingCap: this.props.worker.isDriver ?  this.props.worker.veh_loadingCap : "0",
                veh_frameType: this.props.worker.isDriver ?  this.props.worker.veh_frameType : "Открытый борт" ,
                height: !this.props.worker.isDriver ?  this.props.worker.height : "0",
                weight: !this.props.worker.isDriver ?  this.props.worker.weight : "0",
                rating: props.worker.rating,
            }
        }

    }


    render() {
        let { classes, worker } = this.props;
        let { pending, shouldAdd, workerInfo, worker_id } = this.state;


        return <Card>
            <CardBody>

                <GridContainer>

                    <GridItem   xs={12} sm={12} md={12}>
                        <TextField label="Balance" name="balance" onChange={this.handleChange} />
                    </GridItem>
                    <GridItem xs={12} sm={12} md={12}>
                        <TextField label="Login" name="login" onChange={this.handleChange} />
                    </GridItem>
                    <GridItem id='worker_phone'   xs={6} sm={6} md={6}>
                        <TextField label="Phone number" name="phoneNum" onChange={this.handleChange} />
                    </GridItem>
                    <GridItem  xs={12} sm={12} md={12}>
                        <TextField label="Address" name="address" onChange={this.handleChange} />
                    </GridItem>
                    </GridContainer>

                </GridContainer>
            </CardBody>
        </Card>
    }
}

I have realised 2 methods handleChange but they dont seems good.

The first method works, but i think it is not a good idea to make a copy of the state.

handleChange = (is_check = false) => (e) => {

    let value = e.target[is_check ? "checked" : "value"]
    this.updateState(e.target.name, value);
}

updateState = async (field, value) => {
    //Slow method
    field = 'workerInfo.'+field
    let init_state = _.clone(this.state, true);

    _.set(init_state, field, value);
    await this.setState(init_state);
}

The second method are not working at all.

It destroys all fields inside the workerInfo and put only one, which was changed.

handleChange = () => async event => {   
    const name = event.target.name

    await this.setState({workerInfo:{ [name]: event.target.value}})
    });
};  

Using of previous state give incorrect result too.

this.setState((prevState) => {
            return {workerInfo: { ...prevState.workerInfo, [name]: event.target.value}}
        });

So what is the way to implement universal changeHandler function, which will be update the state, using name of the textfield to link with state.workerInfo field?

SkaaRJ
  • 173
  • 1
  • 1
  • 14

1 Answers1

3

This simple change handler I can think of using prevState is this,

handleChange = (event) => {   

  const { name, value } = event.target;

  this.setState(prevState => ({
     workerInfo:{ 
       ...prevState.workerInfo,
       [name]: value
     }}
  ), ()=> console.log(this.state.workerInfo))
} 

Note: I think there is no need to use async/await while updating state.

Malakai
  • 3,011
  • 9
  • 35
  • 49
ravibagul91
  • 20,072
  • 5
  • 36
  • 59