I am trying to display a new text input based on the selected option. I am able to do that as below but the old value entered is always present no matter what I change the new select option to.
What might be a better way to achieve this? Appreciate any suggestions.
class loadComponent extends React.Component {
static propTypes = {
......
};
static defaultProps = {
....
};
constructor() {
super();
this.state = {
value: ""
};
}
state = {
...
};
reset = (selected) => {
this.setState({
selectedInputName: selected.target[selected.target.selectedIndex].text,
selectedInputId: selected.target.value
});
};
makeTextInput = () => {
return (
<TextInput
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
value={this.state.value}
/>
);
};
render() {
let newInputText = '';
if (this.state.selectedInputId !== '') {
newInputText = this.makeTextInput();
}
return (
<Select
label="What would you like to search with?"
options={this.props.searchOptions}
onChange={selected => this.reset(selected)}
/>
<div className="search margin_bottom_large">
{newInputText}
);
I am trying to display a new text input based on the selected option. I am able to do that as below but the old value entered is always present no matter what I change the new select option to.
What might be a better way to achieve this? Appreciate any suggestions.
class loadComponent extends React.Component {
static propTypes = {
......
};
static defaultProps = {
....
};
constructor() {
super();
this.state = {
value: ""
};
}
state = {
...
};
reset = (selected) => {
this.setState({
selectedInputName: selected.target[selected.target.selectedIndex].text,
selectedInputId: selected.target.value
});
};
makeTextInput = () => {
return (
<TextInput
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
value={this.state.value}
/>
);
};
render() {
let newInputText = '';
if (this.state.selectedInputId !== '') {
newInputText = this.makeTextInput();
}
return (
<Select
label="What would you like to search with?"
options={this.props.searchOptions}
onChange={selected => this.reset(selected)}
/>
<div className="search margin_bottom_large">
{newInputText}
);
Share
Improve this question
edited Aug 14, 2017 at 17:53
oyeesh
asked Aug 14, 2017 at 15:09
oyeeshoyeesh
58110 silver badges29 bronze badges
3
- so basically you want to clear the current input from the user when the input type is changed? – canaan seaton Commented Aug 14, 2017 at 15:19
- @canaanseaton Yeah, Thats exactly what I am trying to achieve. – oyeesh Commented Aug 14, 2017 at 15:30
- okay, see my solution below. Doing something of that sort will allow you to reset the value of the input anytime you want, say when an input type changes. – canaan seaton Commented Aug 14, 2017 at 15:31
3 Answers
Reset to default 3makeTextInput
function creates a new object, but from react
's perspective it's the same ponent because react
distinguishes them by looking at their type
and key
. To make react recreate an element, you have to change one of those values.
This code changes type
of NewInputText
element each time it renders (because NewInputText
always refers to a new function):
reset = (selected) => {
this.setState({
selectedInputName: selected.target[selected.target.selectedIndex].text,
selectedInputId: selected.target.value
});
};
makeTextInput = () => {
return (
<TextInput
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
/>
);
};
render() {
let NewInputText = () => '';
if (this.state.selectedInputId !== '') {
NewInputText = () => this.makeTextInput();
}
return (
<Select
label="What would you like to search with?"
options={this.props.searchOptions}
onChange={selected => this.reset(selected)}
/>
<div className="search margin_bottom_large">
<NewInputText />
);
This code assigns different key to TextInput
each time:
reset = (selected) => {
this.setState({
selectedInputName: selected.target[selected.target.selectedIndex].text,
selectedInputId: selected.target.value
});
};
makeTextInput = () => {
return (
<TextInput
key={Math.random()}
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
/>
);
};
render() {
let newInputText = '';
if (this.state.selectedInputId !== '') {
newInputText = this.makeTextInput();
}
return (
<Select
label="What would you like to search with?"
options={this.props.searchOptions}
onChange={selected => this.reset(selected)}
/>
<div className="search margin_bottom_large">
{newInputText}
);
Is there a better way to do this?
I think using the controlled ponent design pattern would be ideal in this situation.
class SomeInput extends Component {
constructor() {
super();
this.state = {
value: "" //Keep value state here
};
}
render() {
/* Doing something like the following will allow you to clear
the input value simply by doing the following..
this.setState({ value: '' });
*/
return (
<Input
type="text"
onChange={e => this.setState({ value: e.target.value })} // set value state to entered text
value={this.state.value} // set value of input to value piece of state
/>
);
}
}
This will give you full access to the current value of the input, thereby allowing you to set it to anything or clear it at anytime or for any event simply by doing the following this.setState({ value: '' })
.
Don't know the rest of your code which could be handy but you can try:
makeTextInput = () => (
<TextInput
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
/>
);
change = (event) => {
this.setState({
selectedInputName: event.target.value
});
}
render() {
return (
<Select
label="What would you like to search with?"
options={this.props.searchOptions}
onChange={this.change}
/>
<div className="search margin_bottom_large">
{this.makeTextInput()}
);
What you need to do is only setState properly. Each time you change a state the ponent will be re-rendered which means that the makeTextInput
method will be triggered.
EDIT:
by the way, it is good idea to use getter
for returning ponent in render method, in this case:
get textInput() {
return (
<TextInput
label={this.state.selectedInputName}
placeholder={`Please enter ${this.state.selectedInputName} here!`}
onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
showClear
/>
);
}
and then in render method, just use {this.textInput}