在我自己的可重用组件中包装一个 TextField
Wrapping a TextField in my own reusable component
所以我有一个组件,它在输入的文本开头添加了一个 *
,如下所示:
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'
/>
现在,当我开始输入时,一切都很好。
如果我更改上面的代码并在 MyTextField
上添加 value='test'
prop
,一切都会中断。它出现是因为我在 TextField
中添加了一个 prop
,它不能被 MyTextField
value={this.state.value}
覆盖。
那么我怎样才能添加 prop
value
并且仍然在输入文本的开头添加 *
?
另一部分是,如果用户添加了自己的 onChange
,我怎样才能同时调用 MyTextField
和使用 MyTextField
onChange
事件的组件?
=======编辑 1 的开始===============
@Patrick - 我已根据您的评论进行了调整,第一部分现在正在运行。所以我可以输入 <TextField />
并看到更改。
变化如下:
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 >
);
}
无论如何,谢谢你的帮助。
=======编辑 1 结束===============
=======编辑 2 的开始===============
我通过添加我自己的名为 onNewValueChange
的事件并在 onChange
中调用它来修复 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) }
/>
@Patrick 谢谢你的帮助,让我朝着正确的方向前进。
=======编辑 2 结束===============
总的来说,我认为这种在组件内部传递所有其他内容之前省略 props 的模式令人困惑,至少对我而言。尽可能明确应该始终是一个优先事项。
如果我理解正确,预期的行为如下:
- 您可以传递默认文本,您的组件应在该文本前加上 * 前缀。
- 您可以修改文本,但无论您如何修改,都应始终以 * 为前缀 - 因此空字符串应该只是 *。
我创建了这个 fiddle 希望它能达到您的意思:https://jsfiddle.net/69z2wepo/78041/
关键概念是将 props 和 state 分开,一个 prop 只传递一次,并且应该真正负责你的初始状态
这是我创建的两个 类:
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}/>)
}
}
所以我有一个组件,它在输入的文本开头添加了一个 *
,如下所示:
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'
/>
现在,当我开始输入时,一切都很好。
如果我更改上面的代码并在 MyTextField
上添加 value='test'
prop
,一切都会中断。它出现是因为我在 TextField
中添加了一个 prop
,它不能被 MyTextField
value={this.state.value}
覆盖。
那么我怎样才能添加 prop
value
并且仍然在输入文本的开头添加 *
?
另一部分是,如果用户添加了自己的 onChange
,我怎样才能同时调用 MyTextField
和使用 MyTextField
onChange
事件的组件?
=======编辑 1 的开始===============
@Patrick - 我已根据您的评论进行了调整,第一部分现在正在运行。所以我可以输入 <TextField />
并看到更改。
变化如下:
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 >
);
}
无论如何,谢谢你的帮助。
=======编辑 1 结束===============
=======编辑 2 的开始===============
我通过添加我自己的名为 onNewValueChange
的事件并在 onChange
中调用它来修复 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) }
/>
@Patrick 谢谢你的帮助,让我朝着正确的方向前进。
=======编辑 2 结束===============
总的来说,我认为这种在组件内部传递所有其他内容之前省略 props 的模式令人困惑,至少对我而言。尽可能明确应该始终是一个优先事项。
如果我理解正确,预期的行为如下:
- 您可以传递默认文本,您的组件应在该文本前加上 * 前缀。
- 您可以修改文本,但无论您如何修改,都应始终以 * 为前缀 - 因此空字符串应该只是 *。
我创建了这个 fiddle 希望它能达到您的意思:https://jsfiddle.net/69z2wepo/78041/
关键概念是将 props 和 state 分开,一个 prop 只传递一次,并且应该真正负责你的初始状态
这是我创建的两个 类:
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}/>)
}
}