react:如果输入值因状态而变化,则触发 onChange?

IT技术 javascript reactjs
2021-02-22 13:59:28

编辑:我不想仅在单击按钮时才调用 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'))

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

6个回答

您需要onChange手动触发事件。在文本输入上 onChange 监听input事件。

所以在你的handleClick函数中你需要触发事件

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

完整代码

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'))

代码笔

编辑:正如@Samuel 在评论中所建议的,一种更简单的方法是调用handleChangefrom handleClickif you don't need to the event objectin handleChangelike

handleClick () {
    this.setState({value: 'another random text'})
    this.handleChange();
  }

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

@ShubhamKhatri 抱歉,我要撤回我的投票。我刚刚意识到你的回答没有回答我的问题。您正在做的是从 handleClick 显式调用 handleChange 方法。这与 handleClick 无关。React 状态不知道 handleClick 方法对吗?我会给你一个更实际的例子,我们可能需要这个。假设您有一个登录表单并保存了密码。当您再次进入登录页面时,您的表单输入会被浏览器自动填充。现在您要为某些 UI 动画调用 handleChange 方法。
2021-04-21 13:59:28
@SamuelScheiderich 如果您不希望 handleChange 中的 onChange 事件对象,那当然是一种更简单的方法。我没有将它包含在原始答案中,因为 handleChange 包含该事件作为参数
2021-04-29 13:59:28
在元素上使用 ref 几乎总是错误的答案,除非您需要做一些其他方式无法完成的事情。在这里,一个简单的解决方案是简单地从 handleClick 调用 handleChange,如以下答案所示:stackoverflow.com/a/42550931/2608603
2021-05-01 13:59:28
对于 2019 年根本不起作用。dispatchEvent由于某种原因,表单现在对手册没有反应
2021-05-04 13:59:28
@ShubhamKhatri,美好的一天 Shubham,很好的答案,我想问你一个问题,我们是否应该总是对输入字段使用 onChange 处理程序。我只是在创建计算器并决定使用例如 <input value:this.state.number> 而不使用 onChange。我只是改变状态,然后输入的值也会改变。这是正确的方法吗?还是应该在使用输入字段时始终使用 onChange?:)
2021-05-07 13:59:28

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

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

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

解决方案是在输入上调用本机值设置器(请参阅以下代码中的 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

结果

在此处输入图片说明

prototypeValueSetter.callvalueSetter.call切换?在上面的示例中,valueSetter只有在 a) 未定义或 b) 严格等于 时才会调用prototypeValueSetter
2021-04-18 13:59:28
这正是我要找的,谢谢伙计:)
2021-04-21 13:59:28
我在他们切换的情况下测试了代码 - 不起作用。因此,我认为没有理由不专门使用prototypeValueSetter和删除valueSetter.
2021-05-14 13:59:28

我认为你应该像这样改变它:

<input value={this.state.value} onChange={(e) => {this.handleChange(e)}}/>

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

因此,如果您想在handleChange()单击按钮时调用,请执行以下操作:

<button onClick={this.handleChange.bind(this)}>Change Input</button>

或者

handleClick () {
  this.setState({value: 'another random text'});
  this.handleChange();
}
我想在单击按钮时触发 handleChange。它通过在输入中手动输入来工作。假设输入是只读的。
2021-04-30 13:59:28

其他答案讨论了渲染中的直接绑定,因此我想补充几点。

不建议您直接在渲染中或组件中除构造函数之外的任何其他地方绑定函数。因为对于每个函数绑定,都会在 webpack 包 js 文件中创建一个新的函数/对象,因此包的大小会增加。您的组件将出于多种原因重新渲染,例如何时执行 setState、收到新props、何时执行this.forceUpdate()等。因此,如果您直接在渲染中绑定函数,它将始终创建一个新函数。而是始终在构造函数中进行函数绑定,并在需要时调用引用。通过这种方式,它只创建一次新函数,因为每个组件只调用一次构造函数。

你应该怎么做,如下所示

constructor(props){
  super(props);
  this.state = {
    value: 'random text'
  }
  this.handleChange = this.handleChange.bind(this);
}

handleChange (e) {
  console.log('handle change called');
  this.setState({value: e.target.value});
}

<input value={this.state.value} onChange={this.handleChange}/>

您也可以使用箭头函数,但在某些情况下,每次组件重新渲染时,箭头函数也会创建新函数。你应该知道什么时候使用箭头函数,什么时候不应该使用。有关何时使用箭头函数的详细说明,请在此处查看接受的答案

这个答案完全忽略了实际问题。而在你的答案给出的信息是有value一般来说,我不认为无关的答案应该存在,因为它只会造成混乱的人试图找到实际有用的这恰好(或接近)回答的话题
2021-04-16 13:59:28

您必须执行以下 4 个步骤:

  1. 创建事件

    var event = new Event("change",{
        detail: {
            oldValue:yourValueVariable,
            newValue:!yourValueVariable
        },
        bubbles: true,
        cancelable: true
    });
    event.simulated = true;
    let tracker = this.yourComponentDomRef._valueTracker;
    if (tracker) {
        tracker.setValue(!yourValueVariable);
    }
    
  2. 将值绑定到组件 dom

    this.yourComponentDomRef.value = !yourValueVariable;
    
  3. 绑定元素 onchange 以响应 onChange 函数

     this.yourComponentDomRef.onchange = (e)=>this.props.onChange(e);
    
  4. 分派事件

    this.yourComponentDomRef.dispatchEvent(event);
    

在上面的代码中yourComponentDomRef,例如参考你的 React 组件的 master dom<div className="component-root-dom" ref={(dom)=>{this.yourComponentDomRef= dom}}>

这是一大堆不正确的伏都教代码集合,你不想解释。根据我的经验,只有_valueTracker确实必要的event.simulated = true,其余的都没有意义。你为什么要这样做value = !yourValueVariable完全没有意义。不妨将其添加5. jump on your head and roll twice on your back“必须做”的所谓步骤的一部分。
2021-04-20 13:59:28