首页 > 解决方案 > 嵌套组件失去对第一个 onchange 的关注

问题描述

我有以下 3 个组件,第一个更改输入字段使其失去焦点。我试过提供输入字段和 div 键,但它没有解决我的问题。我是 React 的新手,所以我可能做错了一些基本的事情。我没有在渲染方法中创建新函数,这是 stackoverflow 中记录的大多数失去焦点问题的原因。因此,新职位的原因。

索引.tsx

import * as React from "react";
import { IQuery, Queries } from "./components/Queries/Queries";

interface IManageResponseState {
  primaryQuery: IQuery;
  alternateQueries: IQuery[];
}

export class ManageResponse extends React.Component<any, IManageResponseState> {

  constructor(props: any) {
    super(props);
    this.state = {
      primaryQuery: {
        queryText: "This is my primary query text",
        id: 0
      }, alternateQueries: [{
        queryText: "this is my alternate query text 1",
        id: 1
      },
      {
        queryText: "this is my alternate query text 2",
        id: 2
      }]
    };
    this.addFunc = this.addFunc.bind(this);
    this.removeFunc = this.removeFunc.bind(this);
    this.primaryChangedFunc = this.primaryChangedFunc.bind(this);
    this.alternateChangedFunc = this.alternateChangedFunc.bind(this);
  }

  public addFunc(text: string) {
    const newQueries = this.state.alternateQueries.filter(q => true);
    newQueries.push({ id: 0, queryText: text });
    this.setState({ alternateQueries: newQueries });
  };

  public removeFunc(index: number) {
    this.setState({ alternateQueries: this.state.alternateQueries.splice(index, 1) });
    console.log("Remove called:" + index);
  };

  public primaryChangedFunc(text: string) {
    const query = {
      queryText: text,
      id: 0
    };

    this.setState({ primaryQuery: query });
    console.log("changed primary called:" + text);
  }

  public alternateChangedFunc(index: number, text: string) {
    const item = this.state.alternateQueries[index];
    const newQueries = this.state.alternateQueries.filter(q => true);
    newQueries[index] = {
      queryText: text,
      id: item.id
    };

    this.setState({ alternateQueries: newQueries })
    console.log("changed alternate called:" + text);
  }

  public render() {
    return (
      <React.Fragment>
        <Queries primaryQuery={this.state.primaryQuery} alternateQueries={this.state.alternateQueries} onAddQuery={this.addFunc} onRemoveQuery={this.removeFunc} onPrimaryChanged={this.primaryChangedFunc} onAlternateQueryChanged={this.alternateChangedFunc} />
      </React.Fragment>
    );
  }
}

查询.tsx

import * as classnames from 'classnames';
import * as React from "react";
import { AlternateQueryItem } from "../AlternateQueryItem/AlternateQueryItem";
import './Queries.scss'

export interface IQuery {
  queryText: string;
  id: number;
}

export interface IQueryProps {
  primaryQuery: IQuery;
  alternateQueries: IQuery[];
  onPrimaryChanged: (queryText: string) => void;
  onAlternateQueryChanged: (index: number, queryText: string) => void;
  onAddQuery: (queryText: string) => void;
  onRemoveQuery: (atIndex: number) => void;
}

interface IQueryState {
  primaryQueryInvalid: boolean;
}

class Queries extends React.Component<IQueryProps, IQueryState> {
  constructor(props: IQueryProps) {
    super(props);
    this.onPrimaryQueryChanged = this.onPrimaryQueryChanged.bind(this);
    this.state = { primaryQueryInvalid: false };
  }

  public render() {
    return (
      <main className="query-main-container">
        <div className="primary-query-container">
          <div className="form-group">
            <h5 className={classnames("primary-query-header", { 'invalid': this.state.primaryQueryInvalid })}>Primary query</h5>
            <div className="primary-query">
            <div>{ "hello " +  this.state.primaryQueryInvalid }</div>
              <input type="text" value={this.props.primaryQuery.queryText} onChange={this.onPrimaryQueryChanged} className="form-control"/>
            </div>
          </div>
        </div>

        <div>
          <h5 className="query-header">Query variations</h5>
          <hr />
        </div>
        <div className="query-container">
          {this.props.alternateQueries && this.props.alternateQueries.map((q, i) => this.renderQuery(q, i))}
        </div>
      </main>
    );
  }
  public renderQuery(query: IQuery, key: number) {
    return (
      <AlternateQueryItem onChanged={this.props.onAlternateQueryChanged} query={query} key={key} index={key} />
    );
  }

  private onPrimaryQueryChanged = (ev: React.FormEvent<HTMLInputElement>) => {
    this.setState({ primaryQueryInvalid: ev.currentTarget.value === ""})
    this.props.onPrimaryChanged(ev.currentTarget.value)
  }
}

export { Queries };

AlternateQueryItem.tsx

import * as React from "react";
import { IQuery } from "../Queries/Queries";

export interface IAlternateQueryProps {
  query: IQuery;
  onChanged: (index: number, queryText: string) => void;
  index: number;
}

class AlternateQueryItem extends React.Component<IAlternateQueryProps> {
  constructor(props: IAlternateQueryProps) {
    super(props);
    this.onItemChanged = this.onItemChanged.bind(this);
  }

  public render() {
    return (
      <div className="form-group">
        <div className="alternate-query">
          <input type="text" value={this.props.query.queryText} onChange={this.onItemChanged} className="form-control" />
        </div>
      </div>
    );
  }

  public onItemChanged = (ev: any) => {
    this.props.onChanged(this.props.index, ev.currentTarget.value)
  }
}

export { AlternateQueryItem };

标签: reactjstypescript

解决方案


推荐阅读