Reputation: 36723
I have a simple React/Spring boot app where I'd like to pass a search string to a detail page, then link back to the parent using the same searchString as a parameter.
At that point, the parent page should take the value and store it back in the state.
As far as the existing code, when the parent opens, it sets a bunch of values in the state, including the search string:
constructor(props) {
super(props);
const {cookies} = props;
this.state = {
word: '',
newWord: '',
searchString: '',
licenses: [],
licensePage: [],
csrfToken: cookies.get('XSRF-TOKEN'),
isLoading: true,
licensesPerPage: 7,
activePage: 1,
begin: 0,
end: 7
};
The detail page (edit page) is called by pressing a button on the parent page:
<Button size="sm" color="primary" tag={Link} to={"/licenses/" + license.id}>Edit</Button>
The detail page returns to the parent by selecting either a "save" or "cancel" button:
<div>
<Button color="primary" type="submit">Save</Button>{' '}
<Button color="secondary" tag={Link} to="/licenses">Cancel</Button>
</div>
The submit is handled by an "onSubmit" function which calls "handleSubmit:
<Form onSubmit={this.handleSubmit}>
This is handleSubmit - only the last line is relevant here:
async handleSubmit(event) {
event.preventDefault();
if(this.handleValidation()){
} else {
return;
}
const {item, csrfToken} = this.state;
await fetch('/api/license' + (item.id ? '/' + item.id : '') , {
method: (item.id) ? 'PUT' : 'POST',
headers: {
'X-XSRF-TOKEN': csrfToken,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item),
credentials: 'include'
});
this.props.history.push('/licenses');
}
It's the last line that I need to change:
this.props.history.push('/licenses');
should be:
this.props.history.push('/license/search/{searchString}');
I just need to populate searchString. I could then apply the same logic to the cancel.
So my question is, how to pass the searchString to the child, then grab it when it's passed to the parent in the URL?
======================= Attempt to implement answer failing on "not a fuction" error ==========
I tried the answer, but haven't been able to convert it to a class-based approach (I'm using classes, not function).
Here's the code. Note that I've temporarily added "2" to the variable names so it doesn't get confused with existing code.
App.js
import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import LicenseList from './LicenseList';
import LicenseEdit from './LicenseEdit';
import ImportList from './ImportList';
import { CookiesProvider } from 'react-cookie';
class App extends Component {
state = {
searchString2: ""
};
updateSearchString2 = (searchString2) => {
this.setState({
searchString2
});
};
render() {
return (
<CookiesProvider>
<Router>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/licenses' exact={true} component={LicenseList}
searchString2={this.state.searchString2} // props passed will be same value passed to DetailsPage
updateSearchString2={this.updateSearchString2}
/>
<Route path='/imports' exact={true} component={ImportList}/>
<Route path='/licenses/:id' component={LicenseEdit}/>
</Switch>
</Router>
</CookiesProvider>
)
}
}
export default App;
Relevant code in license list.js
<div>
<input type="text" value={this.props.searchString2} onChange={(e) => this.props.updateSearchString2(e.target.value)} />
This gives the error
TypeError: _this6.props.updateSearchString2 is not a function
Any thoughts?
Upvotes: 0
Views: 1163
Reputation: 14201
You can have 1 source of truth for the searchString
state such that, this state will be passed down as prop to both the "ParentPage" component and the "DetailsPage" component. For this, you can have a common parent component for both ParentPage & DetailsPage component
export default class App extends React.Component {
state = {
searchString: ""
};
updateSearchString = (searchString) => {
this.setState({
searchString
});
};
render() {
return (
<div className="App">
<Route
exact
path="/"
render={() => (
<ParentPage
searchString={this.state.searchString} // props passed will be same value passed to DetailsPage
updateSearchString={this.updateSearchString}
/>
)}
/>
<Route
path="/license"
render={() => <DetailsPage searchString={this.state.searchString} />}
/>
</div>
);
}
}
In this scenario, regardless of any routing that occurred or any state changes, the searchString
value will remain consistent all through out your components
For this requirement:
The idea is that if searchString is null, the API will return all licences (as "/licenses" does), but if the string contains something, it will return only matching licenses.
since you already have access to the searchString
, at this point you can have condition statements based on the searchString
value and assess whether you need the API to return all licenses or not, etc
Upvotes: 1