2017-04-10 21 views
8

Obecnie próbuję zbudować prostą aplikację reag-redux, która ma dane studentów i kampusu w backend. OnEnter pracował tutaj, ale nie istnieje w nowym routerze reagowania.React-Router v4 onEnter wymiany

Ta aplikacja próbuje wczytać dane początkowe na początku, zamiast robić element componentDidMount w każdym rzeczywistym komponencie. Czy jest to zalecane podejście, czy też istnieją alternatywne wzorce, o których nie wiem?

/* -------------------< COMPONENT >------------------- */ 
import React from 'react'; 

import { BrowserRouter as Router, Route } from 'react-router-dom'; 
import Home from './components/Home'; 
import Students from './components/Students'; 

const Routes = ({ getInitialData }) => { 
    return (
    <Router> 
     <div> 
     <Route exact path="/" component={Home} onEnter={getInitialData} /> 
     <Route path="/students" component={Students} /> 
     <Route path="*" component={Home} /> 
     </div> 
    </Router> 
); 
}; 

/* -------------------< CONTAINER >-------------------- */ 

import { connect } from 'react-redux'; 
import receiveStudents from './reducers/student'; 
import receiveCampuses from './reducers/campus'; 

const mapState = null; 
const mapDispatch = dispatch => ({ 
    getInitialData:() => { 
    dispatch(receiveStudents()); 
    dispatch(receiveCampuses()); 
    } 
}); 

export default connect(mapState, mapDispatch)(Routes); 

Odpowiedz

12

Moje obecne rozwiązanie polega na umieszczeniu dodatkowego kodu w funkcji renderowania, a nie na użyciu właściwości komponentu.

<Route exact path="/" render={() => { 
    getInitialData(); 
    return <Home />; 
} } /> 
+2

Problem polega na tym, że jeśli 'getInitialData' jest asynchroniczny,' ' uczyni zanim to się robi pobierania. Nie narzekam, jest to wina implementacji v4. –

+1

W moich aplikacjach używam niektórych flag, aby pokazać, że dane ładują się i sprawdzam je w komponencie. Podczas ładowania wyświetla się wskaźnik ładowania, więc nie jest tak źle dla mnie – akmed0zmey

5

Jednym z rozwiązań jest użycie hoc

function preCondition(condition, WrappedComponent) { 
    return class extends Component { 
    componentWillMount{ 
      condition() 
    } 

     render() { 
      <WrappedComponent {...this.props} /> 
     } 
    } 
} 

<Route exact path="/" component={preCondition(getInitialData, Home)} /> 
+0

Bardzo podoba mi się twoje rozwiązanie! Czy do tej pory znalazłeś jakiś minus? Wydaje się być idealnym – Ventura

+0

niesamowite ~! dzięki – tcstory

+0

Czy v może wykonywać połączenia asynchroniczne tutaj? – user2396315

7

chcę sugerować nieco innego podejścia. Korzystając z dziedziczenia klas, możesz zaimplementować własny router.

import {Redirect, Route} from 'react-router'; 



/** 
* Class representing a route that checks if user is logged in. 
* @extends Route 
*/ 
class AuthRequiredRoute extends Route{ 
    /** 
    * @example <AuthRequiredRoute path="/" component={Products}> 
    */ 
    render() { 
     // call some method/function that will validate if user is logged in 
     if(!loggedIn()){ 
      return <Redirect to="/login"></Redirect> 
     }else{ 
      return <this.props.component /> 
     } 
    } 
} 
+0

Ładne rozwiązanie! Ale musiałem też dodać "importuj reakcję z" reaguj ";" na górze. –

+0

Świetne rozwiązanie! –

+0

return return nie jest poprawne w tsx. Typ elementu JSX "this.props.component" nie ma żadnych konstrukcji ani sygnatur połączeń. – XGreen