React Router v4에서 히스토리로 푸시하는 방법?
React Router (v3)의 현재 버전에서는 서버 응답을 수락 browserHistory.push
하고 적절한 응답 페이지로 이동하는 데 사용할 수 있습니다. 그러나 이것은 v4에서 사용할 수 없으며이를 처리하는 적절한 방법이 무엇인지 잘 모르겠습니다.
이 예에서 Redux를 사용 하면 사용자가 양식을 제출할 때 components / app-product-form.js가 호출 this.props.addProduct(props)
됩니다. 서버가 성공하면 사용자는 카트 페이지로 이동합니다.
// actions/index.js
export function addProduct(props) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
browserHistory.push('/cart'); // no longer in React Router V4
});
}
React Router v4 기능에서 장바구니 페이지로 리디렉션하려면 어떻게해야합니까?
history
컴포넌트 외부 에서 메소드 를 사용할 수 있습니다 . 다음과 같은 방법으로 시도하십시오.
먼저 history 패키지를history
사용 하는 객체를 만듭니다 .
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
그런 다음에 그것을 포장 <Router>
( 하시기 바랍니다 참고 , 당신은 사용해야하는 import { Router }
대신 import { BrowserRouter as Router }
) :
// src/index.jsx
// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/login">Login</Link></li>
</ul>
<Route exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
</div>
</Router>
</Provider>,
document.getElementById('root'),
);
예를 들어 다음과 같이 어느 곳에서나 현재 위치를 변경하십시오.
// src/actions/userActionCreators.js
// ...
import history from '../history';
export function login(credentials) {
return function (dispatch) {
return loginRemotely(credentials)
.then((response) => {
// ...
history.push('/');
});
};
}
UPD : React Router FAQ 에서 약간 다른 예를 볼 수도 있습니다 .
React Router v4는 v3 (이전)와 근본적으로 다르므로 이전과 동일하게 사용할 수 없습니다 browserHistory.push()
.
이 정보는 더 많은 정보를 원한다면 관련 이있는 것 같습니다.
- 자체 히스토리 인스턴스를 작성하고 해당 변경 사항을 청취
browserHistory
하므로 새 작성은 작동하지 않습니다<BrowserRouter>
. 따라서 다른 인스턴스는 URL을 변경하지만을 업데이트하지는 않습니다<BrowserRouter>
.browserHistory
v4에서는 반응 라우터에 의해 노출되지 않으며 v2에서만 노출됩니다.
대신이 작업을 수행 할 수있는 몇 가지 옵션이 있습니다.
사용
withRouter
상위 구성 요소를대신
withRouter
고차 컴포넌트를 사용하여 히스토리로 푸시 할 컴포넌트로 랩핑해야합니다. 예를 들면 다음과 같습니다.import React from "react"; import { withRouter } from "react-router-dom"; class MyComponent extends React.Component { ... myFunction() { this.props.history.push("/some/Path"); } ... } export default withRouter(MyComponent);
자세한 내용 은 공식 문서 를 확인하십시오 .
당신은에 액세스 얻을 수있는
history
객체의 속성과 가장 가까운<Route>
의match
withRouter 고차원 적 요소를 통해입니다. withRouter는<Route>
렌더 소품 과 동일한 소품으로 경로가 변경 될 때마다 컴포넌트를 다시 렌더링합니다{ match, location, history }
.
context
API 사용컨텍스트를 사용하는 것이 가장 쉬운 솔루션 중 하나 일 수 있지만 실험적인 API 인 경우 불안정하고 지원되지 않습니다. 다른 모든 것이 실패 할 때만 사용하십시오. 예를 들면 다음과 같습니다.
import React from "react"; import PropTypes from "prop-types"; class MyComponent extends React.Component { static contextTypes = { router: PropTypes.object } constructor(props, context) { super(props, context); } ... myFunction() { this.context.router.history.push("/some/Path"); } ... }
문맥 에 대한 공식 문서 를 살펴보십시오 .
응용 프로그램을 안정적으로 유지하려면 컨텍스트를 사용하지 마십시오. 실험적인 API이며 React의 향후 릴리스에서 중단 될 수 있습니다.
이러한 경고에도 불구하고 컨텍스트 사용을 고집하는 경우 컨텍스트 사용을 작은 영역으로 격리하고 가능한 경우 컨텍스트 API를 직접 사용하지 않도록하여 API가 변경 될 때 쉽게 업그레이드하십시오.
이것이 내가 한 방법입니다.
import React, {Component} from 'react';
export default class Link extends Component {
constructor(props) {
super(props);
this.onLogout = this.onLogout.bind(this);
}
onLogout() {
this.props.history.push('/');
}
render() {
return (
<div>
<h1>Your Links</h1>
<button onClick={this.onLogout}>Logout</button>
</div>
);
}
}
this.props.history.push('/cart');
장바구니 페이지로 리디렉션하는 데 사용 하여 내역 개체에 저장됩니다.
즐기세요, 마이클
React Router v4 문서 에 따르면 -Redux Deep Integration 세션
다음을 위해 깊은 통합이 필요합니다.
"조치를 파견하여 탐색 할 수 있습니다"
그러나 이들은 "심층 통합"에 대한 대안으로이 접근 방식을 권장합니다.
"탐색하기 위해 조치를 전달하는 대신 제공된 히스토리 오브젝트를 전달하여 구성 요소를 조치로 라우트하고 거기에서 탐색 할 수 있습니다."
따라서 withRouter 상위 구성 요소로 구성 요소를 랩핑 할 수 있습니다.
export default withRouter(connect(null, { actionCreatorName })(ReactComponent));
히스토리 API를 소품에 전달합니다. 따라서 기록을 매개 변수로 전달하는 액션 제작자를 호출 할 수 있습니다. 예를 들어 ReactComponent 내부에서 :
onClick={() => {
this.props.actionCreatorName(
this.props.history,
otherParams
);
}}
그런 다음 actions / index.js 내부에서
export function actionCreatorName(history, param) {
return dispatch => {
dispatch({
type: SOME_ACTION,
payload: param.data
});
history.push("/path");
};
}
React Router 4에서 가장 간단한 방법은
this.props.history.push('/new/url');
그러나이 방법을 사용하려면 기존 구성 요소에 history
객체에 대한 액세스 권한이 있어야 합니다. 우리는 액세스 할 수 있습니다
컴포넌트가
Route
직접 링크 된 경우 컴포넌트는 이미history
오브젝트에 액세스 할 수 있습니다.예 :
<Route path="/profile" component={ViewProfile}/>
여기
ViewProfile
에 액세스 할 수history
있습니다.Route
직접 연결되지 않은 경우 .예 :
<Route path="/users" render={() => <ViewUsers/>}
그런 다음
withRouter
기존 구성 요소를 뒤틀기 위해 heigher order fension 을 사용해야 합니다.내부
ViewUsers
구성 요소import { withRouter } from 'react-router-dom';
export default withRouter(ViewUsers);
이제
ViewUsers
구성 요소가history
객체에 액세스 할 수 있습니다.
최신 정보
2
-이 시나리오에서는 모든 경로 props
를 구성 요소로 전달한 다음 구성 요소에서 액세스 할 수 있습니다 this.props.history
.HOC
예 :
<Route path="/users" render={props => <ViewUsers {...props} />}
불쾌한 질문, 많은 시간이 걸렸지 만 결국은이 방법으로 해결했습니다.
용기를 포장 withRouter
하고 작업 내역을 mapDispatchToProps
기능에 전달하십시오 . 실제로 history.push ( '/ url')을 사용하여 탐색하십시오.
동작:
export function saveData(history, data) {
fetch.post('/save', data)
.then((response) => {
...
history.push('/url');
})
};
컨테이너:
import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
return {
save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));
이는 React Router v4.x에 유효합니다 .
this.context.history.push
작동 안 할 것이다.
나는 다음과 같이 푸시 작업을 수행했다.
static contextTypes = {
router: PropTypes.object
}
handleSubmit(e) {
e.preventDefault();
if (this.props.auth.success) {
this.context.router.history.push("/some/Path")
}
}
이 경우 소품을 썽크에 전달합니다. 그래서 당신은 단순히 전화
props.history.push('/cart')
그렇지 않은 경우 여전히 구성 요소에서 기록을 전달할 수 있습니다
export function addProduct(data, history) {
return dispatch => {
axios.post('/url', data).then((response) => {
dispatch({ type: types.AUTH_USER })
history.push('/cart')
})
}
}
다른 사람에게 가치가있는 경우를 대비하여 하나 이상의 솔루션을 제공합니다.
나는이 history.js
내가 다음이 파일을 :
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history
다음으로 라우터를 정의하는 루트에서 다음을 사용합니다.
import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'
export default class Root extends React.Component {
render() {
return (
<Provider store={store}>
<Router history={history}>
<Switch>
...
</Switch>
</Router>
</Provider>
)
}
}
마지막으로, actions.js
나는 역사를 가져 와서 pushLater를 사용합니다.
import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)
이렇게하면 API 호출 후 새로운 작업을 수행 할 수 있습니다.
그것이 도움이되기를 바랍니다!
를 사용하여이 작업을 수행 할 수있었습니다 bind()
. 의 버튼을 클릭하고 index.jsx
일부 데이터를 서버에 게시하고 응답을 평가하고로 리디렉션하고 싶었 습니다 success.jsx
. 내가 그 일을 어떻게했는지 ...
index.jsx
:
import React, { Component } from "react"
import { postData } from "../../scripts/request"
class Main extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
this.postData = postData.bind(this)
}
handleClick() {
const data = {
"first_name": "Test",
"last_name": "Guy",
"email": "test@test.com"
}
this.postData("person", data)
}
render() {
return (
<div className="Main">
<button onClick={this.handleClick}>Test Post</button>
</div>
)
}
}
export default Main
request.js
:
import { post } from "./fetch"
export const postData = function(url, data) {
// post is a fetch() in another script...
post(url, data)
.then((result) => {
if (result.status === "ok") {
this.props.history.push("/success")
}
})
}
success.jsx
:
import React from "react"
const Success = () => {
return (
<div className="Success">
Hey cool, got it.
</div>
)
}
export default Success
그래서 바인딩에 의해 this
에 postData
에 index.jsx
, 나는 액세스 할 수 있었다 this.props.history
에서 request.js
바로 확인 내가 포함하는 기억하게해야 ... 그때 다른 구성 요소에서이 기능을 다시 사용할 수 있습니다 this.postData = postData.bind(this)
에 constructor()
.
콜백을 사용하십시오. 그것은 나를 위해 일했다!
export function addProduct(props, callback) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
callback();
});
}
컴포넌트에서 콜백을 추가하기 만하면됩니다.
this.props.addProduct(props, () => this.props.history.push('/cart'))
여기 내 해킹이 있습니다 (이것은 루트 디렉토리 파일이며 약간의 redux가 혼합되어 있습니다 react-router-redux
.
const store = configureStore()
const customHistory = createBrowserHistory({
basename: config.urlBasename || ''
})
ReactDOM.render(
<Provider store={store}>
<Router history={customHistory}>
<Route component={({history}) => {
window.appHistory = history
return (
<App />
)
}}/>
</Router>
</Provider>,
document.getElementById('root')
)
그런 다음 window.appHistory.push()
원하는 어디에서나 사용할 수 있습니다 (예 : redux store 함수 / thunks / sagas 등) 방금 사용할 수 있기를 희망 했지만 URL이 변경되었지만 window.customHistory.push()
어떤 이유로 든 react-router
업데이트되지 않는 것 같습니다. 그러나이 방법으로 EXACT 인스턴스가 react-router
사용합니다. 나는 세계적인 범위에 물건을 넣는 것을 좋아하지 않으며, 이것이 내가 할 수있는 몇 가지 중 하나입니다. 그러나 IMO를 본 다른 대안보다 낫습니다.
Redux를 사용하는 경우 npm package react-router-redux를 사용하는 것이 좋습니다 . Redux 상점 탐색 조치를 전달할 수 있습니다.
Readme 파일에 설명 된대로 상점을 작성해야 합니다 .
가장 쉬운 사용 사례 :
import { push } from 'react-router-redux'
this.props.dispatch(push('/second page'));
컨테이너 / 컴포넌트의 두 번째 사용 사례 :
컨테이너:
import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import Form from '../components/Form';
const mapDispatchToProps = dispatch => ({
changeUrl: url => dispatch(push(url)),
});
export default connect(null, mapDispatchToProps)(Form);
구성 요소:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class Form extends Component {
handleClick = () => {
this.props.changeUrl('/secondPage');
};
render() {
return (
<div>
<button onClick={this.handleClick}/>
</div>Readme file
);
}
}
React router V4는 이제 히스토리 소품을 아래와 같이 사용할 수있게합니다 :
this.props.history.push("/dummy",value)
그런 다음 위치 소품이 state:{value}
구성 요소 상태가 아닌 사용 가능한 모든 위치에 값에 액세스 할 수 있습니다 .
내가 로그인하고 다른 일을 할 때처럼 이렇게 사용할 수 있습니다.
class Login extends Component {
constructor(props){
super(props);
this.login=this.login.bind(this)
}
login(){
this.props.history.push('/dashboard');
}
render() {
return (
<div>
<button onClick={this.login}>login</login>
</div>
)
/*Step 1*/
myFunction(){ this.props.history.push("/home"); }
/**/
<button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go
Home</button>
1 단계는 라우터에서 앱을 포장
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
이제 내 전체 앱이 BrowserRouter에 액세스 할 수 있습니다. 2 단계 루트를 가져온 다음 해당 소품을 전달합니다. 아마도 기본 파일 중 하나에있을 것입니다.
import { Route } from "react-router-dom";
//lots of code here
//somewhere in my render function
<Route
exact
path="/" //put what your file path is here
render={props => (
<div>
<NameOfComponent
{...props} //this will pass down your match, history, location objects
/>
</div>
)}
/>
이제 컴포넌트 js 파일에서 console.log (this.props)를 실행하면 다음과 같은 것을 얻을 수 있습니다
{match: {…}, location: {…}, history: {…}, //other stuff }
2 단계 기록 개체에 액세스하여 위치를 변경할 수 있습니다
//lots of code here relating to my whatever request I just ran delete, put so on
this.props.history.push("/") // then put in whatever url you want to go to
또한 저는 코딩 부트 캠프 학생 일 뿐이므로 전문가는 아니지만 사용할 수 있다는 것도 알고 있습니다
window.location = "/" //wherever you want to go
내가 틀렸다면 정정하십시오. 그러나 그것을 테스트 할 때 React를 사용하는 전체 요점을 물리 쳤다고 생각한 전체 페이지를 다시로드했습니다.
그래서 그것을 할 방법은 다음과 같습니다 - 사용하는 대신 리디렉션의 history.push
, 난 그냥 사용 Redirect
에서 구성 요소를 react-router-dom
그냥 통과 할 수이 구성 요소를 사용하는 경우 push=true
, 그것은 알아서합니다
import * as React from 'react';
import { Redirect } from 'react-router-dom';
class Example extends React.Component {
componentDidMount() {
this.setState({
redirectTo: '/test/path'
});
}
render() {
const { redirectTo } = this.state;
return <Redirect to={{pathname: redirectTo}} push={true}/>
}
}
Router
자체적 으로 사용자 정의 를 작성하십시오 browserHistory
.
import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory();
const ExtBrowserRouter = ({children}) => (
<Router history={history} >
{ children }
</Router>
);
export default ExtBrowserRouter
다음으로를 정의한 루트에서 Router
다음을 사용하십시오.
import React from 'react';
import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';
//Use 'ExtBrowserRouter' instead of 'BrowserRouter'
import ExtBrowserRouter from './ExtBrowserRouter';
...
export default class Root extends React.Component {
render() {
return (
<Provider store={store}>
<ExtBrowserRouter>
<Switch>
...
<Route path="/login" component={Login} />
...
</Switch>
</ExtBrowserRouter>
</Provider>
)
}
}
마지막으로 history
필요한 곳을 가져 와서 사용하십시오.
import { history } from '../routers/ExtBrowserRouter';
...
export function logout(){
clearTokens();
history.push('/login'); //WORKS AS EXPECTED!
return Promise.reject('Refresh token has expired');
}
참고 URL : https://stackoverflow.com/questions/42701129/how-to-push-to-history-in-react-router-v4
'development' 카테고리의 다른 글
레일스 루트 디렉토리 경로? (0) | 2020.03.15 |
---|---|
Redis에 사용되는 기본 데이터 구조는 무엇입니까? (0) | 2020.03.15 |
Android Marshmallow에서 특정 앱의 권한 화면을 프로그래밍 방식으로 여는 방법은 무엇입니까? (0) | 2020.03.15 |
모바일 웹 페이지에서 확대 / 축소를 어떻게 비활성화 할 수 있습니까? (0) | 2020.03.15 |
비밀번호 프롬프트없이 우분투에 MySQL 설치 (0) | 2020.03.15 |