React history.push() 不渲染新组件
React history.push() not rendering new component
我有一个具有简单登录功能的 React.js 项目。用户获得授权后,我调用 history.push 方法更改地址栏中的 link 但不呈现新组件。 (我使用 BrowserRouter)
我的index.js组件:
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<BrowserRouter>
<Main />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
我的Main.js组件:
const Main = (props) => {
return (
<Switch>
<Route exact path="/" component={Signin} />
<Route exact path="/servers" component={Servers} />
</Switch>
)}
export default withRouter(Main);
我的 Action Creator:
export const authorization = (username, password) => (dispatch) =>
new Promise ((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
})
}).then( response => {
if (response.ok) {
response.json().then( result => {
console.log("API reached.");
dispatch(logUserIn(result.token));
resolve(result);
})
} else {
let error = new Error(response.statusText)
error.response = response
dispatch(showError(error.response.statusText), () => {throw error})
reject(error);
}
});
});
我的Signin.js组件:
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
this.props.history.push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
最奇怪的是,如果我将 handleSubmit() 方法更改为此 - 一切正常:
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token);
//this.props.history.push('/servers')
});
this.props.history.push('/servers')
}
如果我尝试从 componentWillReceiveProps(newProps)
方法推送历史记录,则会出现同样的问题 - 它会更改地址但不会呈现新组件。有人可以解释为什么会发生这种情况以及如何解决吗?
不处理这个 ->
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
this.props.history.push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
因为在这个 handleSubmit
方法中你在一个承诺中调用 this.props.history.push()
所以 this
指向承诺的实例而不是你当前的 class 实例。
试试这个 ->
handleSubmit(event) {
event.preventDefault();
const { history: { push } } = this.props;
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
现在在这个声明中 ->
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token);
//this.props.history.push('/servers')
});
this.props.history.push('/servers')
}
您调用 this.props.history.push() 是正确的,因为它超出了承诺并引用了当前 Class 实例。
尝试使用自定义历史记录和路由器而不是 BrowserRouter。安装历史后:
yarn add history
创建自定义浏览器历史记录:
import { createBrowserHistory } from "history";
export default createBrowserHistory();
在您的设置中使用 Router 而不是 BrowserRouter:
import history from "your_history_file";
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<Router history={history}>
<Main />
</Router>
</Provider>,
document.getElementById('root')
);
或者如果您不想使用自定义历史文件并从那里导入,您可以直接在 index.js:
中将其打包
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<Router history={history}>
<Main />
</Router>
</Provider>,
document.getElementById('root')
);
如果有人感兴趣 - 发生这种情况是因为应用程序在推送历史记录之前正在呈现。当我将历史推送放入我的操作中但就在结果转换为 JSON 之前,它开始工作,因为它现在推送历史然后才呈现应用程序。
export const authorization = (username, password, history) => (dispatch) =>
new Promise ((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
})
}).then( response => {
if (response.ok) {
//################################
//This is where I put it
history.push("/servers");
//################################
response.json().then( result => {
dispatch(logUserIn(result.token));
resolve(result);
})
} else {
let error = new Error(response.statusText)
error.response = response
dispatch(showError(error.response.statusText), () => {throw error})
reject(error);
}
});
});
您需要申请 withRouter 在每个使用 "push"
的组件中使用 this.props.history.push('/page')
import { withRouter } from 'react-router-dom';
.....
export default
withRouter(MoneyExchange);
这在使用推送时很重要。
首先,使用 history 包创建一个历史对象:
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
然后将其包装在主路由器组件中。
import { Router, Route, Link } from 'react-router-dom';
import history from './history';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Fragment>
<Header />
<Switch>
<SecureRoute exact path="/" component={HomePage} />
<Route exact path={LOGIN_PAGE} component={LoginPage} />
<Route exact path={ERROR_PAGE} component={ErrorPage} />
</Switch>
<Footer />
</Fragment>
</Router>
</Provider>)
这里,发送请求后,重定向到首页。
function requestItemProcess(value) {
return (dispatch) => {
dispatch(request(value));
history.push('/');
};
}
应该会有帮助:)
我在使用 react-electron-boilerplate,在使用 MemoryRouter
时遇到问题
使用 history.push('/someUrl')
无效...
只需在组件中使用 exact
属性,然后 initialEntries
设置默认路由。
<Router initialEntries={['/']}>
<Switch>
<Route exact path="/" component={LoginScreen} />
<Route exact path="/session" component={SessionScreen} />
</Switch>
</Router>
我有一个具有简单登录功能的 React.js 项目。用户获得授权后,我调用 history.push 方法更改地址栏中的 link 但不呈现新组件。 (我使用 BrowserRouter)
我的index.js组件:
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<BrowserRouter>
<Main />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
我的Main.js组件:
const Main = (props) => {
return (
<Switch>
<Route exact path="/" component={Signin} />
<Route exact path="/servers" component={Servers} />
</Switch>
)}
export default withRouter(Main);
我的 Action Creator:
export const authorization = (username, password) => (dispatch) =>
new Promise ((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
})
}).then( response => {
if (response.ok) {
response.json().then( result => {
console.log("API reached.");
dispatch(logUserIn(result.token));
resolve(result);
})
} else {
let error = new Error(response.statusText)
error.response = response
dispatch(showError(error.response.statusText), () => {throw error})
reject(error);
}
});
});
我的Signin.js组件:
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
this.props.history.push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
最奇怪的是,如果我将 handleSubmit() 方法更改为此 - 一切正常:
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token);
//this.props.history.push('/servers')
});
this.props.history.push('/servers')
}
如果我尝试从 componentWillReceiveProps(newProps)
方法推送历史记录,则会出现同样的问题 - 它会更改地址但不会呈现新组件。有人可以解释为什么会发生这种情况以及如何解决吗?
不处理这个 ->
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
this.props.history.push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
因为在这个 handleSubmit
方法中你在一个承诺中调用 this.props.history.push()
所以 this
指向承诺的实例而不是你当前的 class 实例。
试试这个 ->
handleSubmit(event) {
event.preventDefault();
const { history: { push } } = this.props;
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token); //I do get "success" in console
push('/servers') //Changes address, does not render /servers component
});
}
const mapActionsToProps = {
onLoginRequest: authorization
}
现在在这个声明中 ->
handleSubmit(event) {
event.preventDefault();
this.setState({ isLoading: true })
const { username, password } = this.state;
this.props.onLoginRequest(username, password, this.props.history).then(result => {
console.log("Success. Token: "+result.token);
//this.props.history.push('/servers')
});
this.props.history.push('/servers')
}
您调用 this.props.history.push() 是正确的,因为它超出了承诺并引用了当前 Class 实例。
尝试使用自定义历史记录和路由器而不是 BrowserRouter。安装历史后:
yarn add history
创建自定义浏览器历史记录:
import { createBrowserHistory } from "history";
export default createBrowserHistory();
在您的设置中使用 Router 而不是 BrowserRouter:
import history from "your_history_file";
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<Router history={history}>
<Main />
</Router>
</Provider>,
document.getElementById('root')
);
或者如果您不想使用自定义历史文件并从那里导入,您可以直接在 index.js:
中将其打包import { createBrowserHistory } from "history";
const history = createBrowserHistory();
ReactDOM.render(
<Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
<Router history={history}>
<Main />
</Router>
</Provider>,
document.getElementById('root')
);
如果有人感兴趣 - 发生这种情况是因为应用程序在推送历史记录之前正在呈现。当我将历史推送放入我的操作中但就在结果转换为 JSON 之前,它开始工作,因为它现在推送历史然后才呈现应用程序。
export const authorization = (username, password, history) => (dispatch) =>
new Promise ((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
})
}).then( response => {
if (response.ok) {
//################################
//This is where I put it
history.push("/servers");
//################################
response.json().then( result => {
dispatch(logUserIn(result.token));
resolve(result);
})
} else {
let error = new Error(response.statusText)
error.response = response
dispatch(showError(error.response.statusText), () => {throw error})
reject(error);
}
});
});
您需要申请 withRouter 在每个使用 "push"
的组件中使用 this.props.history.push('/page')import { withRouter } from 'react-router-dom';
.....
export default
withRouter(MoneyExchange);
这在使用推送时很重要。
首先,使用 history 包创建一个历史对象:
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
然后将其包装在主路由器组件中。
import { Router, Route, Link } from 'react-router-dom';
import history from './history';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Fragment>
<Header />
<Switch>
<SecureRoute exact path="/" component={HomePage} />
<Route exact path={LOGIN_PAGE} component={LoginPage} />
<Route exact path={ERROR_PAGE} component={ErrorPage} />
</Switch>
<Footer />
</Fragment>
</Router>
</Provider>)
这里,发送请求后,重定向到首页。
function requestItemProcess(value) {
return (dispatch) => {
dispatch(request(value));
history.push('/');
};
}
应该会有帮助:)
我在使用 react-electron-boilerplate,在使用 MemoryRouter
使用 history.push('/someUrl')
无效...
只需在组件中使用 exact
属性,然后 initialEntries
设置默认路由。
<Router initialEntries={['/']}>
<Switch>
<Route exact path="/" component={LoginScreen} />
<Route exact path="/session" component={SessionScreen} />
</Switch>
</Router>