无法从 React 组件中的道具访问历史记录?
Unable to access the history from the props in a component in React?
我有一个名为 (EnterSystem) 的基本组件,我正在其上调用 (Login) 和 (Register) 组件。我通过在登录组件中使用 {...this.props}
将道具从进入系统传递到登录和注册。提交数据并使用数据库对其进行验证后,我使用 this.props.history.push("/enterprises")
将其重定向到其他组件 (ListEnterprises)。但我需要 (ListEnterprise) 组件中的这段历史,以将其进一步重定向到其他组件。但是 this.props
是未定义的。任何人都可以帮忙吗?
进入系统
class EnterSystem extends Component {
constructor(props) {
super(props);
this.state = {
isLogginActive: true
};
}
componentDidMount() {
//Add .right by default
this.rightSide.classList.add("right");
}
changeState() {
const { isLogginActive } = this.state;
if (isLogginActive) {
this.rightSide.classList.remove("right");
this.rightSide.classList.add("left");
} else {
this.rightSide.classList.remove("left");
this.rightSide.classList.add("right");
}
this.setState(prevState => ({ isLogginActive: !prevState.isLogginActive }));
}
render() {
const { isLogginActive } = this.state;
const current = isLogginActive ? "Register" : "Login";
const currentActive = isLogginActive ? "login" : "register";
return (
<div>
<NavigationComponent />
<div className="Enter">
<div className="login">
<div className="container" ref={ref => (this.container = ref)} >
{isLogginActive && (
<Login {...this.props} containerRef={ref => (this.current = ref)} />
)}
{!isLogginActive && (
<Register {...this.props} containerRef={ref => (this.current = ref)} />
)}
</div>
<RightSide current={current} currentActive={currentActive} containerRef={ref => (this.rightSide = ref)} onClick={this.changeState.bind(this)} />
</div>
</div>
<FooterComponent />
</div>
);
}
}
const RightSide = props => {
return (
<div className="right-side" ref={props.containerRef} onClick={props.onClick}>
<div className="inner-container">
<div className="text">{props.current}</div>
</div>
</div>
);
};
export default EnterSystem;
登录
export class Login extends Component {
emptyCredential = {
username: "",
password: "",
}
constructor(props) {
super(props);
this.state = {
isLoading: false,
hasLoginFailed: false,
showSuccessMessage: false,
credential: this.emptyCredential
}
this.handleChange = this.handleChange.bind(this);
this.loginClicked = this.loginClicked.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
let updatedCredential = { ...this.state.credential };
updatedCredential[name] = value;
this.setState({ credential: updatedCredential });
console.log(updatedCredential);
}
loginClicked(event) {
const payload = this.state.credential;
console.log("Printing Payload ");
console.log(payload);
console.log(payload.username);
console.log(payload.password)
AuthenticationService.executeJwtAuthenticationService(payload)
.then(response => {
console.log(response.data);
AuthenticationService.registerSuccessfulLoginForJwt(payload.username, response.data.id_token);
this.setState({ isLoading: false, hasLoginFailed: false, showSuccessMessage: true });
this.props.history.push("/enterprises");
// // <Redirect to={{
// // pathname: '/enterprises'
// // }}
// // />
// <ListEnterprises name="history" historyId="this.props" />
// this.props.history.push({ pathname: "/enterprises" });
})
.catch(error => {
console.log(error);
this.setState({ isLoading: false, hasLoginFailed: true, showSuccessMessage: false });
});
}
render() {
return (
<div className="base-container" ref={this.props.containerRef}>
<div className="header">Login</div>
<div className="content">
<div className="image">
<img src={LoginImg} />
</div>
{this.state.hasLoginFailed && <div className="alert alert-warning">Invalid Credentials</div>}
{this.state.showSuccessMessage && <div>Login Sucessful</div>}
<div className="form">
<div className="form-group">
<label htmlFor="username" for="username">Username</label>
<input type="text" name="username" id="username" placeholder="username" onChange={this.handleChange} />
</div>
<div className="form-group">
<label htmlFor="password" for="password">Password</label>
<input type="password" name="password" id="password" placeholder="password" onChange={this.handleChange} />
</div>
</div>
</div>
<div className="footer">
<button type="button" className="btn" onClick={this.loginClicked}>Login</button>
</div>
</div>
);
}
}
ListEnterprises
class ListEnterprises extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
enterprises: [],
message: null,
showFormMessage: false,
}
//Any method in a react component should be bound to this
this.refreshEnterprises = this.refreshEnterprises.bind(this);
}
// After all the elements of the page is rendered correctly, this method is called.
// After the markup is set on the page, this technique called by React itself to either fetch the data from An External API or perform some unique operations which need the JSX.API
// componentDidMount() method is the perfect place, where we can call the setState() method to change the state of our application and render() the updated data loaded JSX. For example, we are going to fetch any data from an API then API call should be placed in this lifecycle method,
// and then we get the response, we can call the setState() method and render the element with updated data.
//React defines a component lifecycle. componentDidMount will be called as soon as the component is mounted. We are calling refreshCourses as soon as a component is mounted.
componentDidMount() {
this.refreshEnterprises();
}
_showMessage = (bool) => {
this.setState({
showFormMessage: bool
});
}
refreshEnterprises() {
EnterpriseService.retrieveAllEnterprises()
.then((response) => {
console.log(response.data);
this.setState({ enterprises: response.data, isLoading: false });
}).catch((error) => {
console.log(error);
});
}
render() {
console.log("Rendering Enterprises");
if (this.state.isLoading)
return (<div>Loading...</div>);
return (
<div>
<NavigationComponent /><br /><br />
<h3 align="center">Here are all your Enterprises</h3><br />
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<Container>
<Table striped bordered hover size="sm">
<thead>
<tr>
<th>Enterprise</th>
<th>Industry</th>
<th>Description</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
this.state.enterprises.map(
enterprise =>
<tr key={enterprise.id}>
<td>{enterprise.enterpriseName}</td>
<td>{enterprise.industry}</td>
<td>{enterprise.description}</td>
<td><button className="btn btn-success">Update</button></td>
<td><button className="btn btn-warning">Delete</button></td>
</tr>
)
}
</tbody>
</Table>
</Container>{" "}{" "}{" "}
<div className="container">
<Button color="primary" size="lg" onClick={this._showMessage.bind(null, true)}>Add Enterprise</Button>{' '}
<Button color="secondary" size="lg" onClick={this._showMessage.bind(null, false)}>Hide</Button>{' '}
{this.state.showFormMessage && (<AddEnterprise {...this.props} />)}
</div>
<FooterComponent />
</div >
);
}
}
export default ListEnterprises;
App.js(此处定义路由)
class App extends Component {
state = {}
render() {
return (
<Router>
<Switch>
<Route path="/" exact={true} component={Home} />
<Route path="/enter" exact={true} component={EnterSystem} />
<Route path="/enterprises"><ListEnterprises /></Route>
// {/* <Route path='/categories' exact={true} component={Category} /> */}
{/* <Route path='/expenses' exact={true} component={Expenses} /> */}
</Switch>
</Router>
);
}
}
export default App;
需要将 props 从 ListEnterprises 发送到 AddEnterprise。
提前感谢您的帮助。
将 withRouter
HOC(高阶组件)添加到您的组件并按如下方式使用它:
import { withRouter } from "react-router";
class ListEnterprises extends Component {/* Your component code goes here */}
export default withRouter(ListEnterprises);
确保 <ListEnterprises />
作为 Route component 加载,history
将自动在 props 中提供,并且可以使用 this.props.history
.
访问
<Route path="/enterprises" component={ListEnterprises} />
我有一个名为 (EnterSystem) 的基本组件,我正在其上调用 (Login) 和 (Register) 组件。我通过在登录组件中使用 {...this.props}
将道具从进入系统传递到登录和注册。提交数据并使用数据库对其进行验证后,我使用 this.props.history.push("/enterprises")
将其重定向到其他组件 (ListEnterprises)。但我需要 (ListEnterprise) 组件中的这段历史,以将其进一步重定向到其他组件。但是 this.props
是未定义的。任何人都可以帮忙吗?
进入系统
class EnterSystem extends Component {
constructor(props) {
super(props);
this.state = {
isLogginActive: true
};
}
componentDidMount() {
//Add .right by default
this.rightSide.classList.add("right");
}
changeState() {
const { isLogginActive } = this.state;
if (isLogginActive) {
this.rightSide.classList.remove("right");
this.rightSide.classList.add("left");
} else {
this.rightSide.classList.remove("left");
this.rightSide.classList.add("right");
}
this.setState(prevState => ({ isLogginActive: !prevState.isLogginActive }));
}
render() {
const { isLogginActive } = this.state;
const current = isLogginActive ? "Register" : "Login";
const currentActive = isLogginActive ? "login" : "register";
return (
<div>
<NavigationComponent />
<div className="Enter">
<div className="login">
<div className="container" ref={ref => (this.container = ref)} >
{isLogginActive && (
<Login {...this.props} containerRef={ref => (this.current = ref)} />
)}
{!isLogginActive && (
<Register {...this.props} containerRef={ref => (this.current = ref)} />
)}
</div>
<RightSide current={current} currentActive={currentActive} containerRef={ref => (this.rightSide = ref)} onClick={this.changeState.bind(this)} />
</div>
</div>
<FooterComponent />
</div>
);
}
}
const RightSide = props => {
return (
<div className="right-side" ref={props.containerRef} onClick={props.onClick}>
<div className="inner-container">
<div className="text">{props.current}</div>
</div>
</div>
);
};
export default EnterSystem;
登录
export class Login extends Component {
emptyCredential = {
username: "",
password: "",
}
constructor(props) {
super(props);
this.state = {
isLoading: false,
hasLoginFailed: false,
showSuccessMessage: false,
credential: this.emptyCredential
}
this.handleChange = this.handleChange.bind(this);
this.loginClicked = this.loginClicked.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
let updatedCredential = { ...this.state.credential };
updatedCredential[name] = value;
this.setState({ credential: updatedCredential });
console.log(updatedCredential);
}
loginClicked(event) {
const payload = this.state.credential;
console.log("Printing Payload ");
console.log(payload);
console.log(payload.username);
console.log(payload.password)
AuthenticationService.executeJwtAuthenticationService(payload)
.then(response => {
console.log(response.data);
AuthenticationService.registerSuccessfulLoginForJwt(payload.username, response.data.id_token);
this.setState({ isLoading: false, hasLoginFailed: false, showSuccessMessage: true });
this.props.history.push("/enterprises");
// // <Redirect to={{
// // pathname: '/enterprises'
// // }}
// // />
// <ListEnterprises name="history" historyId="this.props" />
// this.props.history.push({ pathname: "/enterprises" });
})
.catch(error => {
console.log(error);
this.setState({ isLoading: false, hasLoginFailed: true, showSuccessMessage: false });
});
}
render() {
return (
<div className="base-container" ref={this.props.containerRef}>
<div className="header">Login</div>
<div className="content">
<div className="image">
<img src={LoginImg} />
</div>
{this.state.hasLoginFailed && <div className="alert alert-warning">Invalid Credentials</div>}
{this.state.showSuccessMessage && <div>Login Sucessful</div>}
<div className="form">
<div className="form-group">
<label htmlFor="username" for="username">Username</label>
<input type="text" name="username" id="username" placeholder="username" onChange={this.handleChange} />
</div>
<div className="form-group">
<label htmlFor="password" for="password">Password</label>
<input type="password" name="password" id="password" placeholder="password" onChange={this.handleChange} />
</div>
</div>
</div>
<div className="footer">
<button type="button" className="btn" onClick={this.loginClicked}>Login</button>
</div>
</div>
);
}
}
ListEnterprises
class ListEnterprises extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
enterprises: [],
message: null,
showFormMessage: false,
}
//Any method in a react component should be bound to this
this.refreshEnterprises = this.refreshEnterprises.bind(this);
}
// After all the elements of the page is rendered correctly, this method is called.
// After the markup is set on the page, this technique called by React itself to either fetch the data from An External API or perform some unique operations which need the JSX.API
// componentDidMount() method is the perfect place, where we can call the setState() method to change the state of our application and render() the updated data loaded JSX. For example, we are going to fetch any data from an API then API call should be placed in this lifecycle method,
// and then we get the response, we can call the setState() method and render the element with updated data.
//React defines a component lifecycle. componentDidMount will be called as soon as the component is mounted. We are calling refreshCourses as soon as a component is mounted.
componentDidMount() {
this.refreshEnterprises();
}
_showMessage = (bool) => {
this.setState({
showFormMessage: bool
});
}
refreshEnterprises() {
EnterpriseService.retrieveAllEnterprises()
.then((response) => {
console.log(response.data);
this.setState({ enterprises: response.data, isLoading: false });
}).catch((error) => {
console.log(error);
});
}
render() {
console.log("Rendering Enterprises");
if (this.state.isLoading)
return (<div>Loading...</div>);
return (
<div>
<NavigationComponent /><br /><br />
<h3 align="center">Here are all your Enterprises</h3><br />
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<Container>
<Table striped bordered hover size="sm">
<thead>
<tr>
<th>Enterprise</th>
<th>Industry</th>
<th>Description</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
this.state.enterprises.map(
enterprise =>
<tr key={enterprise.id}>
<td>{enterprise.enterpriseName}</td>
<td>{enterprise.industry}</td>
<td>{enterprise.description}</td>
<td><button className="btn btn-success">Update</button></td>
<td><button className="btn btn-warning">Delete</button></td>
</tr>
)
}
</tbody>
</Table>
</Container>{" "}{" "}{" "}
<div className="container">
<Button color="primary" size="lg" onClick={this._showMessage.bind(null, true)}>Add Enterprise</Button>{' '}
<Button color="secondary" size="lg" onClick={this._showMessage.bind(null, false)}>Hide</Button>{' '}
{this.state.showFormMessage && (<AddEnterprise {...this.props} />)}
</div>
<FooterComponent />
</div >
);
}
}
export default ListEnterprises;
App.js(此处定义路由)
class App extends Component {
state = {}
render() {
return (
<Router>
<Switch>
<Route path="/" exact={true} component={Home} />
<Route path="/enter" exact={true} component={EnterSystem} />
<Route path="/enterprises"><ListEnterprises /></Route>
// {/* <Route path='/categories' exact={true} component={Category} /> */}
{/* <Route path='/expenses' exact={true} component={Expenses} /> */}
</Switch>
</Router>
);
}
}
export default App;
需要将 props 从 ListEnterprises 发送到 AddEnterprise。
提前感谢您的帮助。
将 withRouter
HOC(高阶组件)添加到您的组件并按如下方式使用它:
import { withRouter } from "react-router";
class ListEnterprises extends Component {/* Your component code goes here */}
export default withRouter(ListEnterprises);
确保 <ListEnterprises />
作为 Route component 加载,history
将自动在 props 中提供,并且可以使用 this.props.history
.
<Route path="/enterprises" component={ListEnterprises} />