变更事件与React和Typescript混为一谈

时间:2018-08-06 17:43:16

标签: javascript reactjs typescript binding

我用TypeScript和React.js创建了一个简单的应用程序。我将create-react-app与--scripts-version = react-scripts-ts参数一起使用,并获得了可以正常使用的应用程序。

该应用程序现在只有2个组件:App.tsx,一个包含人员列表和Person.tsx的有状态组件,一个无状态功能组件,包含人员数据和名称输入文本。

这是 Person.tsx 的代码:

import * as React from "react";

export interface IPersonProps {
  id: string;
  firstname: string;
  change: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

export const Person: React.SFC<IPersonProps> = props => {
  return (
    <div>
      <h1>
        Hi {props.firstname}
      </h1>
      <input type="text" onChange={props.change} value={props.firstname} />
    </div>
  );
};

这是 App.tsx 的代码:

import * as React from "react";
import "./App.css";
import { Person, IPersonProps } from "./Person";

interface IAppState {
  persons: Array<IPersonProps>,
  showPersons: boolean;
}

class App extends React.Component<{}, IAppState> {

  readonly togglePersonsHandler = () => {
    const show = this.state.showPersons;
    this.setState({showPersons: !show});
  }

  readonly firstnameChangeHandler = (event:React.ChangeEvent<HTMLInputElement>, 
personId: string) => {
    const personIndex = this.state.persons.findIndex(person => {
      return person.id === personId;
    });
    const person = {
      ...this.state.persons[personIndex]
    }

    person.firstname = event.target.value;

    const persons = [...this.state.persons];
    persons[personIndex] = person;

    this.setState({
      persons: persons
    } as IAppState);
  }

  constructor(props: any, state: IAppState) {
    super(props, state);
    this.state = {
      persons: [
        { id: 'a', firstname: "Michael" } as IPersonProps,
        { id: 'b', firstname: "Mel"} as IPersonProps
      ],
      showPersons: false
    };
  }

  public render() {
    let persons = null;

    if (this.state.showPersons) {
      persons = (
        <div>
          {
            this.state.persons.map((person, index) => {
              return <Person 
                id={person.id}
                firstname={person.firstname} 
                key={person.id} 
                change={this.firstnameChangeHandler.bind(this, event,     person.id)} />
            })
          }
        </div>
      )
    }

    return (
      <div className="App">
        <h1>React</h1>
        <button onClick={this.togglePersonsHandler}>Toggle Persons</button>
        {persons}
      </div>
    );
  }  
}

export default App;

通常将名字绑定到输入字段,但不适用于第一个触发的更改事件。触发时,第一个change事件将获得一个空值,并且名字将被设置为一个空字符串。所有其他更改事件似乎都起作用。如您所见,我正在使用TypeScript,并且希望尽可能地保持类型安全...

也许与事件绑定混为一谈。任何帮助都非常欢迎!

该应用程序如下所示: React app with event binding

1 个答案:

答案 0 :(得分:1)

事件绑定确实是这里的问题。为了使其正常工作,我必须将处理程序方法(在render方法中)的调用更改为:

<Person 
  id={person.id}
  firstname={person.firstname} 
  key={person.id} 
  change={this.firstnameChangeHandler.bind(null, person.id)} />

处理程序方法必须将其签名更改为

readonly firstnameChangeHandler = (personId: string, event:React.ChangeEvent<HTMLInputElement>) => {...}

有关部分绑定的文档可以在以下位置找到:

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Partially_applied_functions