将TextField包装在我自己的可重用组件

时间:2017-05-04 23:59:46

标签: reactjs material-ui

所以我有一个组件在文本类型的开头添加*,如下所示:

 export default class MyTextField extends Component {

      constructor() {
    super();
    this.state = {
      value: '',
    };
  }

  static propTypes = {
    onChange: PropTypes.func,
    value: PropTypes.string
  }

  addSymbol(newValue, symbol) {
    return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
  }

  change(input, newValue) {
    console.log(`I am the parent wit newValue ${newValue}.`);
    this.setState({
      value: this.addSymbol(newValue, '*')
    });
  }

  render() {
    const {
      onChange, // eslint-disable-line no-unused-vars
      ...other
    } = this.props;

    return (
      <TextField
        value={this.state.value}
        onChange={this.change.bind(this)}
        {...other } >
      </TextField >
    );
  }
}

现在我在另一个组件中使用MyTextField

 <MyTextField
    style={styleTextFields}
    floatingLabelText='Add text'
    type='text'
  />

现在,当我开始输入时,一切都很好。

如果我更改上面的代码并在value='test'上添加prop MyTextField,一切都会中断。它似乎是因为我向prop添加了TextFieldMyTextField value={this.state.value}无法覆盖prop

那么如何添加value *并在键入文本的开头添加onChange

另一部分是,如果用户添加了自己的MyTextField,我如何才能同时使用MyTextField onChange个事件同时获取<TextField />组件?

=======编辑开始1 ===============

@Patrick - 我根据你的评论进行了调整,第一部分现在正在运行。所以我可以输入export default class MyTextField extends Component { constructor(props) { super(); this.state = { value: props.value ? this.addSymbol(props.value.toString(), '*') : '' }; } static propTypes = { onChange: PropTypes.func, value: PropTypes.string } addSymbol(newValue, symbol) { return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue; } change(input, newValue) { console.log(`I am the parent wit newValue ${newValue}.`); this.setState({ value: this.addSymbol(newValue, '*') }); } render() { const { value, // eslint-disable-line no-unused-vars onChange, // eslint-disable-line no-unused-vars ...other } = this.props; return ( <TextField value={this.state.value} onChange={this.change.bind(this)} {...other } > </TextField > ); } } ,然后看到更改。

更改如下:

onChange

我不确定如何进行render()调整,因为你不应该修改组件状态?

我也在 addSymbol(newValue, symbol) { return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue; } change(input, newValue) { console.log(`I am the parent wit newValue ${newValue}.`); this.setState({ value: this.addSymbol(newValue, '*') }); } render() { const { value, // eslint-disable-line no-unused-vars onChange, // eslint-disable-line no-unused-vars ...other } = this.props; return ( <TextField value={this.addSymbol(this.state.value, '*')} {...other } > </TextField > ); } 函数中尝试了这个,它不起作用:

onChange

无论如何,谢谢你的帮助。

=======结束编辑1 ===============

=======编辑开始2 ===============

我修复了onNewValueChange事件问题,方法是添加我自己的名为onChange的事件并在export default class MyTextField extends Component { constructor() { super(); this.state = { value: props.value ? this.addSymbol(props.value.toString(), '*') : '' }; } static propTypes = { onNewValueChange: PropTypes.func, value: PropTypes.string } addSymbol(newValue, symbol) { return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue; } change(input, newValue) { const value = value: props.value ? this.addSymbol(props.value.toString(), '*') : ''; this.setState({ value: value }); if(this.props.onNewValueChange) { this.props.onNewValueChange(value); } } render() { const { onNewValueChange, // eslint-disable-line no-unused-vars ...other } = this.props; return ( <TextField value={this.state.value} onChange={this.change.bind(this)} {...other } > </TextField > ); } } 中调用它。这是最终的代码:

MyTextField

现在我在另一个组件中使用<MyTextField style={styleTextFields} floatingLabelText='Add text' type='text' onNewValueChange={(newValue) => console.log(newValue) } />

<tr ng-repeat="name in names">
    <td>{{ name.name }}</td>
    <td>{{ name.age }}</td>
</tr>

@Patrick感谢您的帮助,让我朝着正确的方向前进。

=======结束编辑2 ===============

1 个答案:

答案 0 :(得分:0)

一般来说,我认为这种在传递组件内部其他内容之前省略道具的模式令人困惑,至少对我而言。尽可能明确应该始终是优先事项。

如果我理解正确,预期的行为如下:

  1. 您可以传递默认文本,此文本应以组件的前缀为*。
  2. 您可以修改文本,但无论您如何修改它,它都应该以*为前缀 - 所以空字符串应该只是*。
  3. 我创造了这个小提琴,希望能够达到你的意思:https://jsfiddle.net/69z2wepo/78041/

    关键概念是将道具和状态分开,道具只传递一次,并且应该真正负责你的初始状态

    这是我创建的两个类:

    class Input extends React.Component{
      render(){
       return (<input onChange={this.props.onChange} value={this.props.value}/>)
      }
    }
    
    class WrappedInput extends React.Component{
    
      constructor(props){
          super();
    
        let val = props.value || '';
        this.state = {
            value : this.addSymbol(val,'*')
        }
      }
    
      handleChange(e){
        let newVal = e.target.value;
        this.setState({value:this.addSymbol(newVal,'*')});
      }
    
      addSymbol(newValue, symbol) {
        return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
      }
    
      render(){
       return (<Input onChange={this.handleChange.bind(this)} value={this.state.value}/>)
      }
    }