1

I can add e.target.value for taking a value from Input, but I don't know why handleChange() could not take input value correctly, it will get title:SyntheticBaseEvent, on the Option Part, it will receive a correct value as 0,1,2,3. I am using Antd UI. Did I miss something in my code, please help me to resolve it?

  handleChange = (type, v) => {
    this.data.Schedule[type] = v;
  };
      <Input
        placeholder="Please Type Your Title"
        className="todo-ipt"
        value={this.state.curSchedule.title}
        onChange={this.handleChange.bind(this, 'title')}
      />
    </div>
    <Select
      placeholder="Please Type Schedule Type"
      type="date"
      className="todo-select"
      defaultValue={this.state.curSchedule.type}
      onChange={this.handleChange.bind(this, 'type')}
    >
      <Option value="0">Daily</Option>
      <Option value="1">Weekly</Option>
      <Option value="2">Monthly</Option>
      <Option value="3">Quarterly</Option>
    </Select>
3
  • 1
    You are calling bind on an arrow function whose this can't be bound. title is then prepended to the intrinsically passed arguments (event), so type is 'title', v is event and this is unchanged (so remains the outer scope in which the arrow function was declared). see: Can you bind 'this' in an arrow function?, and Passing event to event handler Commented Jan 26, 2021 at 23:25
  • Thanks pilchard, on the Option Part, it will receive a correct value as 0,1,2,3. As you mentioned that should pass event as well? Commented Jan 27, 2021 at 3:42
  • The antd <Select> onChange method passes the selected value, but it doesn't seem to forward the event. (where as the <Input> component doesn't forward the value, but does pass the event.) To make this work with a single handler you would need to account for this inconsistency from antd, but it will be clearer to write separate Input and Select handlers. Commented Jan 27, 2021 at 10:58

1 Answer 1

1

The antd <Select> onChange method passes the selected value, but it doesn't forward the event. (where as the <Input> component doesn't pass the value, but does forward the event.)

To make this work with a single handler using bind() would require you to account for this inconsistency from antd.

const handleChange = (type, v, e) => {
  const value = v !== null ? v : e.target.value; // handle the inconsistent antd arguments
  setCurSchedule(prev => ({ ...prev, [type]: value }))
};

...

<Input
...
  onChange={handleChange.bind(null, 'title', null)}
  // 'v' will be null, 'e' will be the implicitly passed event.
/>

<Select
  ...
  onChange={handleChange.bind(null, 'type')} 
  // 'v' implicitly passed, 'e' will be the selected option (not the event)
>

const { Input, Select } = antd;

const App = () => {
  const [curSchedule, setCurSchedule] = React.useState({ type: 'Daily' });
  console.log(curSchedule);

  const handleChange = (type, v, e) => {
    console.clear();
    console.log('type: ', type, ' v: ', v, ' e: ', e.target);
    const value = v !== null ? v : e.target.value; // handle the inconsistent antd arguments
    setCurSchedule(prev => ({ ...prev, [type]: value }))
  };

  return (
    <div>
      <div>
        <Input
          placeholder="Please Type Your Title"
          className="todo-ipt"
          value={curSchedule.title}
          onChange={handleChange.bind(null, 'title', null)}
        />
      </div>
      <Select
        placeholder="Please Type Schedule Type"
        type="date"
        className="todo-select"
        defaultValue={curSchedule.type}
        onChange={handleChange.bind(null, 'type')}
      >
        <Option value="0">Daily</Option>
        <Option value="1">Weekly</Option>
        <Option value="2">Monthly</Option>
        <Option value="3">Quarterly</Option>
      </Select>
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<!--AntD -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/4.11.2/antd.min.js" integrity="sha512-po2baibyaVyDwINF7gijO2Zbd9HBQDnd81yJNghcwuU+bjb79Qkaf4zopd2mkQJ33aBHLIifLeGwV7+QiyV3wQ==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.11.2/antd.min.css" integrity="sha512-gs6VDTwxBRKAfKFQbN+UR2wCkNoFnPrvLcsEwGtzDDG1Wuwx5w/UhjsnMwm27En67jU0M04ofj8IIctaBmaU+A==" crossorigin="anonymous" />

<div id="react"></div>

But given the inconsistent implementation from antd it is much clearer to pass an arrow function to the the onChange which explicitly displays the differences in the implicitly passed arguments.

<Input
...
  onChange={(event) => handleChange('title', event.target.value)}
/>

<Select
...
  onChange={(value) => handleChange('type', value)}
>

const { Input, Select } = antd;

const App = () => {
  const [curSchedule, setCurSchedule] = React.useState({ type: 'Daily' });
  
  console.log('curSchedule: ', curSchedule);

  const handleChange = (type, value) => {
    console.clear();
    console.log('type: ', type, ' value: ', value);
    setCurSchedule(prev => ({ ...prev, [type]: value }))
  };

  return (
    <div>
      <div>
        <Input
          placeholder="Please Type Your Title"
          className="todo-ipt"
          value={curSchedule.title}
          onChange={(event) => handleChange('title', event.target.value)}
        />
      </div>
      <Select
        placeholder="Please Type Schedule Type"
        type="date"
        className="todo-select"
        defaultValue={curSchedule.type}
        onChange={(value) => handleChange('type', value)}
      >
        <Option value="0">Daily</Option>
        <Option value="1">Weekly</Option>
        <Option value="2">Monthly</Option>
        <Option value="3">Quarterly</Option>
      </Select>
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<!--AntD -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/4.11.2/antd.min.js" integrity="sha512-po2baibyaVyDwINF7gijO2Zbd9HBQDnd81yJNghcwuU+bjb79Qkaf4zopd2mkQJ33aBHLIifLeGwV7+QiyV3wQ==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.11.2/antd.min.css" integrity="sha512-gs6VDTwxBRKAfKFQbN+UR2wCkNoFnPrvLcsEwGtzDDG1Wuwx5w/UhjsnMwm27En67jU0M04ofj8IIctaBmaU+A==" crossorigin="anonymous" />

<div id="react"></div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.