简体   繁体   English

在反应组件内触发更改事件不起作用

[英]Trigger change-event inside react-component not working

I have a simple react-component which contains of a form .我有一个简单的 react-component ,它包含一个form In this form the user has an search-box where to find users.在这种form ,用户有一个搜索框,可以在其中找到用户。 In order to have a valid form, there must be at least 3 users but not more than 6.为了有一个有效的表单,必须有至少 3 个用户但不超过 6 个。

Therefore I've added a hidden field (hidden by surrounding display:none; div) which contains the number of already added users.因此,我添加了一个隐藏字段(由周围的 display:none; div 隐藏),其中包含已添加用户的数量。 This one will show the error-message in case the current number is invalid.如果当前号码无效,这将显示错误消息。

The following code is simplified but shows the main issue I have.以下代码已简化,但显示了我遇到的主要问题。

In my render-call I have:在我的渲染调用中,我有:

render():JSX.Element {
    return (
        <form>
            <ValidatableInput
                input={<Input type="number" value={this.state.users.length.toString()} min={3} max={6} getRef={(el: HTMLInputElement) => this.testElement = el} onChange={() => alert("changed...")} />}
                minValueMessage={"Currently there are " + this.state.users.length + " users. A minimum of 3 is needed"}
                hidden={true} />
            <UserSearch onUserSelected={this.handleUserSelected} />
            // ...
        </form>
    );
}

whereas UserSearch is the component to search for users.UserSearch是搜索用户的组件。 This is mainly an autocomplete-input which triggers the handleUserSelected :这主要是触发handleUserSelected的自动完成输入:

private handleUserSelected = (selectedElement: IUser) : void => {
    // get a copy of the current state
    const newState = { ...this.state };

    // add the user
    newState.users.push(selectedElement);

    // thats what I've tried so far
    this.testElement.dispatchEvent(new Event("change"));
    this.testElement.dispatchEvent(new Event("change", {bubbles: true}));
    this.testElement.onchange(new Event("change"));
    this.testElement.onchange(new Event("change"), {bubbles: true});

    this.setState(newState, () => // here I want to do the triggering as the input has now the new count as value set)
}

However, the console does not show changed at all.但是,控制台根本没有显示changed

How can I call/trigger the change-event manually when something other changed on the component?当组件上的其他内容发生更改时,如何手动调用/触发更改事件?

This is the ValidatableInput-component:这是 ValidatableInput 组件:

export class ValidatableInput extends React.Component<IValidatableInputProps, IValidatableInputState> {
    render(): JSX.Element {
        const { labelText, input, requiredMessage, maxLengthMessage, minValueMessage, hidden } = this.props;

        input.props.onInvalid = this.handleInvalid;
        input.props.onChange = this.handleChange;

        if (hidden) {
            // set height to 0
        }

        return (
            <FormGroup row >
                <Label for={input.props.name} md={3}>{!hidden && labelText}</Label>
                <Col md={9}>
                    <div>
                        {input}
                        {this.state.validityState.valueMissing && <div className={classNames("invalid-feedback")}>{requiredMessage || "This field is required"}</div>}
                        {this.state.validityState.tooLong && <div className={classNames("invalid-feedback")}>{maxLengthMessage || "The field shoud not be longer than " + input.props.maxLength}</div>}
                        {this.state.validityState.rangeOverflow && <div className={classNames("invalid-feedback")}>{maxLengthMessage || "There are too many items. Maximum allowed: " + input.props.max}</div>}
                        {this.state.validityState.rangeUnderflow && <div className={classNames("invalid-feedback")}>{minValueMessage || "There are too less items. Minimum needed: " + input.props.min}</div>}
                    </div>
                </Col>
            </FormGroup>
        );
    }

    private handleInvalid = (ev: React.FormEvent<HTMLInputElement>): any => {
        const input = ev.target as HTMLInputElement;
        this.setState({ validityState: input.validity });
    }

    private handleChange = (ev: React.FormEvent<HTMLInputElement>): any => {
        const input = ev.target as HTMLInputElement;
        this.setState({ validityState: input.validity });
    }
}

Maybe keep it simpler and remove the refs and eventHandling boilerplate.也许让它更简单并删除 refs 和 eventHandling 样板。

Your business logic relies on this.state.users.length , right?您的业​​务逻辑依赖于this.state.users.length ,对吗? So use it on your favor:因此,请对您有利:

handleUserSelected = (selectedElement: IUser) : void => {
  this.setState({
    users: [
      ...this.state.users,
      selectedElement,
    ],
  })
}

render() {
  const { users } = this.state
  const isInvalid = users.length < 3 || users.length > 6

  return (
    <form>
      {isInvalid && <span>Your invalid message</span>}
      <UserSearch ... />
    </form>
  )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM