2

在 ReactJS 中,我正在编写一个无状态组件;
因为我读过避免不必要的状态是最佳实践。

该组件表示当输入框包含值时执行功能的输入字段。

    export const InputField = (props) => {
      
      const InputFieldContentsChanged = (event) => {
        props.onChange(event.target.value);
      };

      return (
        <div data-component="input-field"
          className={(props.value !== "" ? "value": "")}>
          <input type={props.type} value={props.value} onChange={InputFieldContentsChanged} />
          <span className="bar"></span>
          <label>{props.label}</label>
        </div>
      );
    };

    InputField.PropTypes = {
      type: PropTypes.oneOf([ "text", "password" ]).isRequired,
      label: PropTypes.string.isRequired,
      value: PropTypes.string,
      onChange: PropTypes.func.isRequired
    }

现在,我创建了另一个组件,它只是用于测试上述组件的示例。如下所示:

    export const SampleComponent = (props) => {
      
      let componentUsername = "";
      
      const onUsernameChanged = (username) => {
        componentUsername = username;
      };
      
      return (
        <InputField type="text" label="Username" value={componentUsername} onChange={onUsernameChanged} />
      );
    };

因此,我将 绑定value到组件中的自定义变量,当输入字段的内容发生更改时,该变量会更改。

为什么输入字段组件不使用新用户名更新自己?

亲切的问候,

4

2 回答 2

7

我正在编写一个无状态的 React 组件,因为最好的做法是在不需要时避免状态。

在您的代码中,您尝试使用自己的“状态”,它只是一个变量(componentUsername)。但由于它不是 React 状态,因此组件不会在变量更改时重新渲染。React 根本不知道变化。

因此,要么使用通常的方法setState而不是重新分配您自己的“状态”变量,要么将逻辑放在父组件中并将其传递componentUsernameSampleComponentvia 道具:

const SampleComponent = props => (
  <input type="text" onChange={props.onChange} value={props.value} />
);

class ParentComponent extends React.Component {
  constructor() {
    super();
    this.state = { value: '' };
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(e) {
    console.log(e.target.value);
    this.setState({ value: e.target.value });
  }

  render() {
    return (
      <SampleComponent
        value={this.state.value}
        onChange={this.handleInputChange}
      />
    );
  }
}

ReactDOM.render(<ParentComponent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

于 2017-04-19T10:56:12.190 回答
3

功能组件的想法是不对状态或道具进行任何更改。

由于没有重新渲染组件的触发器,因此您不会看到任何更改。

将此更改React.FunctionReact.Component.

const InputField = (props) => {  
  const InputFieldContentsChanged = (event) => {
    console.log(event.target.value);
    props.onChange(event.target.value);
  };

  return (
    <div data-component="input-field"
      className={(props.value !== "" ? "value": "")}>
      <input type={props.type} value={props.value} onChange={InputFieldContentsChanged} />
      <span className="bar"></span>
      <label>{props.label}</label>
    </div>
  );
};

class SampleComponent extends React.Component {
  constructor() {
    super();
    this.state = { componentUsername : ""};
  }
  
  onUsernameChanged = (username) => {
    console.log(username);
    this.setState({componentUsername: username});
  }
  
  render() {
    return (
      <InputField type="text" label="Username" value={this.state.componentUsername} onChange={this.onUsernameChanged} />
    );
  }
};

ReactDOM.render(<SampleComponent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

于 2017-04-19T11:23:31.917 回答