【问题标题】:Clear input in stateless React component清除无状态 React 组件中的输入
【发布时间】:2018-03-26 12:32:12
【问题描述】:

我想在 Input 组件中实现一个 X 图标,它将清除输入字段。如果我控制状态,我可以轻松做到。但是无状态组件真的可以吗? 我使用 react-semantic-ui,它们的有状态组件具有自动控制状态。

所以我想创建一个可以像这样使用的输入:

//Controlled
class App extends React.Component {
  state = {
    value:''
  }

  onChange = (event, props) => {
    this.setState({value: props.value});
  }

  onClearInput = () => {
    this.setState({value: ''});
  }
  
  render() {
    return (
        <MyInput
          clearable
          value={this.state.value}
          onChange={this.onChange}
          onClearInput={this.onClearInput}
        />
      )
  }
}

或者

// Uncontrolled
class App extends React.Component {
  onChange = (event, props) => {
    doSomething(props.value);
  }

  render() {
    return (
        <MyInput
          clearable
          onChange={this.onChange}
        />
      )
  }
}

在第二个示例中,clearable 功能将不起作用,因为我们没有控制值。

MyInput 可以这样实现:

import React from 'react';
import { Input } from 'semantic-ui-react';
import ClearIcon from './ClearIcon';

function MyInput(props) {
  const prepareProps = {...props};
  if (props.clearable) {
    prepareProps.icon=<ClearIcon onClick={props.onClearInput} />;
    delete prepareProps.clearable;
  }
  delete prepareProps.onClearInput;
  return (
    <div className="my-input">
      <Input {...prepareProps} />
    </div>
  );
}
...etc.

我的问题:

  1. clearable 功能必须以受控和不受控的方式工作。

  2. clearable 功能不需要处理程序。最好只提供一个道具并处理引擎盖下 X 按钮的渲染和行为。

我看不出有任何方法可以完成这项工作。有什么想法吗?

【问题讨论】:

  • 为什么它必须在不受控制的输入上工作?
  • @trixn,为什么不呢? :-) 我只想创建一个多功能组件,而不强迫人们以任何特定方式使用它。因此,如果您只是在您的应用程序中输入&lt;MyInput clearable /&gt;,您将获得一个带有 X 按钮的输入,该按钮可以开箱即用。我不认为这是可能的,但也许我错过了一些东西。这就是我问这个问题的原因。
  • 是的,但如果编写的组件被其他人使用,他们为什么要关心它在内部使用受控输入还是不受控输入?我不明白这个问题。
  • 我同意@trixn。您可以使用渲染道具reactjs.org/docs/render-props.html,这将让使用您的组件的人将您控制的道具消耗到他们自己的视图中,或者只是控制输入。我能看到的唯一其他情况是,您的组件的用户必须将ref 传递给他们的输入。
  • 对,人们不应该关心我在内部做什么。但是他们应该能够以受控/不受控的方式使用组件。问题是我无法在内部控制value,因为这样用户将无法设置自己的value。另一方面,如果我不控制value,我无法清除它。 @pkuzhel 我看不到渲染道具如何帮助我。请解释一下好吗?

标签: javascript reactjs semantic-ui


【解决方案1】:

允许组件的用户通过 props 设置值并且仍然能够清除输入很容易实现,例如像这样:

class MyInput extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: props.value || ''};
    }

    handleChange = event => {
        const { onChange } = this.props;
        this.setState({ value: event.currentTarget.value });
        onChange && onChange(event);
    };

    handleClear = () => {
        const { onClearInput } = this.props;
        this.setState({ value: "" });
        onClearInput && onClearInput();
    };

    render() {
        const { value } = this.state;
        const { clearable, onChange, ...inputProps } = this.props;

        const clearIcon = clearable && <ClearIcon onClick={this.handleClear} />;

        return (
            <div className="my-input">
                <Input value={value} icon={clearIcon} onChange={this.handleChange} {...inputProps} />
            </div>
        );
    }
}

您甚至可以通过使用 @pkuzhel 建议的 hoc 或渲染道具使其更具可组合性。

查看this codesandbox example 以了解它的实际效果。

【讨论】:

  • 这并不能解决问题。此类组件的用户将无法完全控制该值。例如尝试以可控的方式使用该组件并将onChange设置为空函数。您可能希望输入在输入时保持空白,但它仍会显示输入的字符。
  • @Andrey 不,不会。查看&lt;Input value={value} icon={clearIcon} onChange={this.handleChange} {...inputProps} /&gt; 行。如果您从外部提供 value 道具,它将覆盖该值。它完全可以从外部控制并且可以清除。我添加了一个代码框示例。
  • @Andrey 如果您对其进行测试,您会发现它完全符合您的要求。
  • 您更改了初始代码,使我的评论变得无关紧要。伟大的。你的代码仍然不能解决我的问题 #2,因为你强迫用户实现他们自己的onClearInput。我设法使用uncontrollable lib 解决了这个问题,稍后会发布答案。
  • @Andrey 很遗憾,当您拒绝理解它时,我浪费了我的时间为您提供正确的解决方案。受控输入不允许自行清零。父级的状态在任何时候都必须是输入的值。所以父级必须自己清除输入,否则输入会从受控切换到不受控。实际上,您所说的“强制”是用户自己控制该值时想要的。这就是为什么它被称为受控。请不要在以后提出您认为自己知道如何保护他人时间的问题。
【解决方案2】:

@安德烈

你会试试下面的代码吗?如果这能解决您的问题,请告诉我。

import React, { Component } from 'react';
import { Input, Button } from 'semantic-ui-react'

class App extends Component {
  clear = () => {
    console.log(this.inputRef.target.value);
    this.inputRef.target.value = '';
  }
  render() {
    return (
      <div className="App">
        <Input placeholder='Search...' onChange={(input) => {input.persist(); this.inputRef = input}} />
        <Button onClick={this.clear}>Clear</Button>
      </div>
    );
  }
}

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 2020-05-03
    • 2016-04-03
    • 2019-12-06
    相关资源
    最近更新 更多