React:如果输入值按状态改变,则触发onChange?

mad*_*arg 29 javascript reactjs

编辑:我不想只在单击按钮时调用handleChange.它与handleClick无关.我在@shubhakhatri回答的评论中给出了一个例子.

我想根据状态更改输入值,值正在改变,但它不会触发handleChange()方法.我该如何触发handleChange()方法?

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    value: 'random text'
    }
  }
  handleChange (e) {
    console.log('handle change called')
  }
  handleClick () {
    this.setState({value: 'another random text'})
  }
  render () {
    return (
      <div>
        <input value={this.state.value} onChange={this.handleChange}/>
        <button onClick={this.handleClick.bind(this)}>Change Input</button>
      </div>
    )
  }
}

ReactDOM.render(<App />,  document.getElementById('app'))
Run Code Online (Sandbox Code Playgroud)

这是codepen链接:http://codepen.io/madhurgarg71/pen/qrbLjp

Muh*_*nir 28

在 2020 年和 2021 年工作的解决方案:

我尝试了其他解决方案,但没有任何效果。这是因为 React.js 中的输入逻辑已更改。详情可以看这个链接:https : //hustle.bizongo.in/simulate-react-on-change-on-Controlled-components-baa336920e04

简而言之,当我们通过改变 state 来改变 input 的值,然后调度 change 事件时,React 将同时注册 setState 和事件,并将其视为重复事件并吞下它。

解决方案是在输入上调用本机值设置器(请参阅以下代码中的 setNativeValue 函数)

示例代码

import React, { Component } from 'react'
export class CustomInput extends Component {

    inputElement = null;
    
    // THIS FUNCTION CALLS NATIVE VALUE SETTER
    setNativeValue(element, value) {
        const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
        const prototype = Object.getPrototypeOf(element);
        const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;

        if (valueSetter && valueSetter !== prototypeValueSetter) {
            prototypeValueSetter.call(element, value);
        } else {
            valueSetter.call(element, value);
        }
    }


    constructor(props) {
        super(props);

        this.state = {
            inputValue: this.props.value,
        };
    }

    addToInput = (valueToAdd) => {
        this.setNativeValue(this.inputElement, +this.state.inputValue + +valueToAdd);
        this.inputElement.dispatchEvent(new Event('input', { bubbles: true }));
    };

    handleChange = e => {
        console.log(e);
        this.setState({ inputValue: e.target.value });
        this.props.onChange(e);
    };

    render() {
        return (
            <div>
                <button type="button" onClick={() => this.addToInput(-1)}>-</button>
                <input
                    readOnly
                    ref={input => { this.inputElement = input }}
                    name={this.props.name}
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button type="button" onClick={() => this.addToInput(+1)}>+</button>
            </div>
        )
    }
}

export default CustomInput
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明


Shu*_*tri 20

您需要onChange手动触发事件.在文本输入onChange侦听input事件.

所以在你的handleClick功能中你需要触发事件

handleClick () {
    this.setState({value: 'another random text'})
    var event = new Event('input', { bubbles: true });
    this.myinput.dispatchEvent(event);
  }
Run Code Online (Sandbox Code Playgroud)

完整的代码

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    value: 'random text'
    }
  }
  handleChange (e) {
    console.log('handle change called')
  }
  handleClick () {
    this.setState({value: 'another random text'})
    var event = new Event('input', { bubbles: true });
    this.myinput.dispatchEvent(event);
  }
  render () {
    return (
      <div>
        <input readOnly value={this.state.value} onChange={(e) => {this.handleChange(e)}} ref={(input)=> this.myinput = input}/>
        <button onClick={this.handleClick.bind(this)}>Change Input</button>
      </div>
    )
  }
}

ReactDOM.render(<App />,  document.getElementById('app'))
Run Code Online (Sandbox Code Playgroud)

Codepen

编辑:正如在评论中建议通过@Samuel,一个简单的办法是打电话handleChangehandleClick,如果你don't need to the event objecthandleChange

handleClick () {
    this.setState({value: 'another random text'})
    this.handleChange();
  }
Run Code Online (Sandbox Code Playgroud)

我希望这是你需要的,它可以帮助你.

  • @ShubhamKhatri 抱歉,我要撤回我的赞成票。我刚刚意识到你的回答没有回答我的问题。您正在做的是从 handleClick 显式调用 handleChange 方法。这与 handleClick 无关。React 状态不知道 handleClick 方法对吗?我会给你一个更实际的例子,我们可能需要这个。假设您有一个登录表单并保存了密码。当您再次进入登录页面时,您的表单输入会被浏览器自动填充。现在您要为某些 UI 动画调用 handleChange 方法。 (2认同)
  • 从2019年起完全无法使用。由于某种原因,表单现在对手动`dispatchEvent`没有反应 (2认同)

Ami*_*min 8

在功能组件中你可以做到这一点,假设我们有一个input[type=number]

const MyInputComponent = () => {
    const [numberValue, setNumberValue] = useState(0);
    const numberInput = useRef(null);

    /**
    * Dispatch Event on Real DOM on Change
    */
    useEffect(() => {
        numberInput.current.dispatchEvent(
            new Event("change", {
                detail: {
                    newValue: numberValue,
                },
                bubbles: true,
                cancelable: true,
            })
        );
    }, [numberValue]);

    return (
        <>
            <input    
                type="number"            
                value={numberValue}             
                ref={numberInput}
                inputMode="numeric"
                onChange={(e) => setNumberValue(e.target.value)}
            />
        </>
    )
}
Run Code Online (Sandbox Code Playgroud)


phi*_*ipp 7

我认为您应该这样更改:

<input value={this.state.value} onChange={(e) => {this.handleChange(e)}}/>
Run Code Online (Sandbox Code Playgroud)

原则上与onClick={this.handleClick.bind(this)}您在按钮上所做的相同。

因此,如果您想在handleChange()单击按钮时打电话,则:

<button onClick={this.handleChange.bind(this)}>Change Input</button>
Run Code Online (Sandbox Code Playgroud)

要么

handleClick () {
  this.setState({value: 'another random text'});
  this.handleChange();
}
Run Code Online (Sandbox Code Playgroud)