Reputation: 107
I have three components, from outermost to innermost: App
=> Welcome
=> SearchBar
. There's a state defined in App
and SearchBar
, but what I want is to get the user-inputted data in SearchBar and display that in a "Results" page. As such, I'm trying to update the state in SearchBar
and have that simultaneously update the state in App
, so that I can pass that data on to another component that's a child of App
(e.g. Results
). I have the following code, but it's only updating the state in SearchBar
and not that in App
.
(I've looked at some examples where the child (in this case SearchBar
) doesn't have its own state, but in this case I think it's necessary since I'm tracking user input. I may be wrong though.)
// App.js
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { value: "" };
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
this.setState({
value: event.target.value
});
}
render() {
return (
<Router>
<div className="AppContainer">
<Route
exact
path="/"
render={props => <SearchBar handleSubmit={this.handleSubmit} />}
/>
...
// Welcome.js
export default class Welcome extends React.Component {
render() {
return (
<div>
<SearchBar handleSubmit={this.props.handleSubmit} />
</div>
...
// SearchBar.js
export default class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = { value: "" };
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
event.preventDefault();
this.setState({ value: event.target.value });
}
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<input
type="text"
placeholder="Search..."
onChange={this.handleChange}
value={this.state.value}
/>
<input type="submit" />
</form>
);
}
}
Then again, I'm quite new to React so this might not be a pattern that you're supposed to use. In any case, I would appreciate advice on how to best solve this.
Upvotes: 0
Views: 148
Reputation: 15688
Since you've already defined a handleSubmit()
event-handler in App.js
and passed it all the way down to your SearchBar.js
component. You can extrapolate the data you need by giving the input tag in your SearchBar a name prop.
class Searchbar extends React.Component {
state = {
value: ""
};
handleOnChange = e => {
this.setState({
value: e.target.value
});
};
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<input
onChange={this.handleOnChange}
value={this.state.value}
name="search"
/>
</form>
);
}
}
Then in App.js
handleSubmit handler, target that name
prop to get the value
in the input.
handleSubmit = e => {
e.preventDefault();
this.setState({
value: e.target.search.value
})
};
This will likely have the least amount of re-renders.
Yes we can totally display a new component upon submitting the form. We just need the help of a second state-value like displayResults
or displayComponent
then by using a simple if-check, we'll just toggle what components to show.
See working example: Code Demo
Upvotes: 1
Reputation: 20755
In SearchBar
component you should pass state
value directly to handleSubmit
function as,
<form onSubmit={(e)=>{e.preventDefault(); this.props.handleSubmit(this.state.value)}}>
In App
component your handleSubmit
function should be,
handleSubmit(inputValue) {
this.setState({
value: inputValue
});
}
Upvotes: 1