reactjs - browserrouter - rotas react




Como passar para o History no React Router v4? (13)

A maneira mais simples do React Router 4 é usar

export function saveData(history, data) {
  fetch.post('/save', data)
     .then((response) => {
       ...
       history.push('/url');
     })
};

Mas, para usar esse método, seu componente existente deve ter acesso ao objeto history . Podemos ter acesso por

  1. Se o seu componente estiver vinculado ao Route diretamente, ele já terá acesso ao objeto de history .

    por exemplo:

    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));

    Aqui o ViewProfile tem acesso ao history .

  2. Se não estiver conectado diretamente à Route .

    por exemplo:

    this.props.history.push('/new/url');

    Então temos que usar withRouter , uma função de ordem mais alta para distorcer o componente existente.

    Componente Inside ViewUsers

    • import { withRouter } from 'react-router-dom';

    • export default withRouter(ViewUsers);

    Agora é isso, seu componente ViewUsers tem acesso ao objeto history .

ATUALIZAR

2 - nesse cenário, passe todos os props rota para o seu componente e, em seguida, podemos acessar this.props.history partir do componente, mesmo sem um HOC

por exemplo:

<Route path="/profile" component={ViewProfile}/>

Na versão atual do React Router (v3), posso aceitar uma resposta do servidor e usar o browserHistory.push para ir para a página de resposta apropriada. No entanto, isso não está disponível na v4 e não tenho certeza de qual é a maneira apropriada de lidar com isso.

Neste exemplo, usando o Redux, o components / app-product-form.js chama this.props.addProduct(props) quando um usuário envia o formulário. Quando o servidor retorna com sucesso, o usuário é levado para a página Carrinho.

// 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
      });
}

Como posso redirecionar para a página Carrinho da função React Router v4?


Aqui está o meu hack (este é o meu arquivo de nível raiz, com um pouco de redux misturado lá - embora eu não esteja usando o 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')
)

Em seguida, posso usar window.appHistory.push() qualquer lugar que eu quiser (por exemplo, em minhas funções de loja redux / thunks / sagas, etc). Eu esperava poder usar window.customHistory.push() mas, por algum motivo, react-router nunca parecia atualizar, mesmo que o URL mudasse. Mas dessa maneira eu tenho a instância EXATA que o react react-router usa. Eu não amo colocar coisas no escopo global, e essa é uma das poucas coisas com as quais eu faria isso. Mas é melhor do que qualquer outra alternativa que eu já vi na IMO.


Crie um Router personalizado com seu próprio 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

Em seguida, na sua raiz onde você define seu Router , use o seguinte:

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>
    )
  }
}

Por fim, importe o history onde precisar e use-o:

import { history } from '../routers/ExtBrowserRouter';
...

export function logout(){
  clearTokens();      
  history.push('/login'); //WORKS AS EXPECTED!
  return Promise.reject('Refresh token has expired');
}

De acordo com a documentação do React Router v4 - sessão Redux Deep Integration

É necessária uma profunda integração para:

"poder navegar enviando ações"

No entanto, eles recomendam essa abordagem como uma alternativa à "profunda integração":

"Em vez de enviar ações para navegar, você pode passar o objeto de histórico fornecido para rotear componentes para suas ações e navegar com ele até lá."

Assim, você pode agrupar seu componente com o componente de alta ordem withRouter:

export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

que passará a API do histórico para adereços. Assim, você pode ligar para o criador da ação, passando o histórico como um parâmetro. Por exemplo, dentro do seu ReactComponent:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

Em seguida, dentro de actions / index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}

Foi assim que eu fiz:

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>
        );
    }
}

Use this.props.history.push('/cart'); para redirecionar para a página do carrinho, ela será salva no objeto histórico.

Aproveite Michael.


Nesse caso, você está passando adereços para o seu thunk. Então você pode simplesmente ligar

props.history.push('/cart')

Se não for esse o caso, você ainda pode passar o histórico do seu componente

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}

O React Router v4 é fundamentalmente diferente da v3 (e anterior) e você não pode browserHistory.push() como costumava fazer.

Esta discussão parece relacionada se você quiser obter mais informações:

  • Criar um novo browserHistory não funcionará porque o <BrowserRouter> cria sua própria instância do histórico e escuta as alterações. Portanto, uma instância diferente alterará o URL, mas não atualizará o <BrowserRouter> .
  • browserHistory não é exposto pelo browserHistory -router na v4, apenas na v2.

Em vez disso, você tem algumas opções para fazer isso:

  • Use o withRouter alta ordem withRouter

    Em vez disso, você deve usar o componente de ordem superior withRouter -lo no componente que será enviado ao histórico. Por exemplo:

    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);

    Confira a documentação oficial para mais informações:

    Você pode obter acesso às propriedades do objeto history e à correspondência mais próxima do <Route> através do componente de ordem superior withRouter. O withRouter renderizará novamente seu componente toda vez que a rota for alterada com os mesmos objetos que <Route> render props: { match, location, history } .

  • Use a API de context

    Usar o contexto pode ser uma das soluções mais fáceis, mas, sendo uma API experimental, é instável e sem suporte. Use-o apenas quando tudo mais falhar. Aqui está um exemplo:

    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");
      }
      ...
    }

    Veja a documentação oficial sobre o contexto:

    Se você deseja que seu aplicativo seja estável, não use o contexto. É uma API experimental e é provável que ocorra em versões futuras do React.

    Se você insistir em usar o contexto, apesar desses avisos, tente isolar o uso do contexto em uma pequena área e evite usar a API de contexto diretamente quando possível, para facilitar a atualização quando a API for alterada.


Questão desagradável, demorou bastante tempo, mas acabei resolvendo assim:

Envolva seu contêiner com withRouter e passe o histórico para sua ação na função mapDispatchToProps . Em ação, use history.push ('/ url') para navegar.

Açao:

<Route path="/users" render={() => <ViewUsers/>}

Recipiente:

<Route path="/users" render={props => <ViewUsers {...props} />}

Isso é válido para o React Router v4.x.


Use retorno de chamada. Funcionou para mim!

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();
  });
}

No componente, basta adicionar o retorno de chamada

this.props.addProduct(props, () => this.props.history.push('/cart'))

Você pode usar os métodos de history fora dos seus componentes. Tente da seguinte maneira.

Primeiro, crie um objeto de history usado no pacote de histórico :

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Em seguida, envolva-o em <Router> ( observe , você deve usar import { Router } vez de 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'),
);

Altere sua localização atual de qualquer lugar, por exemplo:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
        // ...
        history.push('/');
      });
  };
}

UPD : Você também pode ver um exemplo um pouco diferente nas Perguntas frequentes sobre o React Router .


primeiro passo, envolva seu aplicativo no roteador

import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

Agora todo o meu aplicativo terá acesso ao BrowserRouter. Etapa 2: Importo o Route e, em seguida, passo os adereços. Provavelmente em um dos seus arquivos principais.

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>
      )}
    />

Agora, se eu executar o console.log (this.props) no meu arquivo js componente, devo obter algo parecido com isto

{match: {…}, location: {…}, history: {…}, //other stuff }

Etapa 2 Posso acessar o objeto histórico para alterar minha localização

//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

Além disso, sou apenas um estudante de código de inicialização, por isso não sou especialista, mas sei que você também pode usar

window.location = "/" //wherever you want to go

Corrija-me se estiver errado, mas quando testei isso, recarreguei a página inteira, o que pensei ter derrotado todo o ponto de usar o React.


você pode usá-lo assim como eu faço isso para login e muitas coisas diferentes

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>




react-router-v4