Reaccionar Carga perezosa

Buen dia


Estoy desarrollando un proyecto en React y Redux. Quiero describir la arquitectura de mi proyecto en este artículo.

Entonces comencemos. Estructura de archivo:



Para conectar reductores, cree una clase singleton reducerRegister:

./reducerRegister.js
class ReducerRegistry { constructor () { if (!ReducerRegistry.instance) { this._emitChange = null this._reducers = {} ReducerRegistry.instance = this } return ReducerRegistry.instance } getReducers () { return {...this._reducers} } register (name, reducer) { this._reducers = {...this._reducers, [name]: reducer} if (this._emitChange) { this._emitChange(this.getReducers()) } } setChangeListener (listner) { this._emitChange = listner } } const reducerRegistry = new ReducerRegistry() export default reducerRegistry 

Con esta clase, los reductores pueden registrarse en la tienda.

Crea una tienda:


./configureStore
 export default function configureStore (initialState) { const combine = (reducers) => { const reducerNames = Object.keys(reducers) Object.keys(initialState).forEach(item => { if (reducerNames.indexOf(item) === -1) { reducers[item] = (state = null) => state } }) reducers['router'] = connectRouter(history) return combineReducers(reducers) } const reducer = combine(reducerRegistry.getReducers()) const store = createStore(reducer, initialState, compose(composeWithDevTools(applyMiddleware(thunk)), applyMiddleware(routerMiddleware(history)))) reducerRegistry.setChangeListener(reducers => { store.replaceReducer(combine(reducers)) }) return store } 

Usando la función store.replaceReducer, cargue los reductores en la tienda.

Archivo principal


Agregar rutas y conectar redux

./index.js
 const Cabinet = React.lazy(() => import('./moduleCabinet/Index')) let store = configureStore({ profile: {loading: null} }) class App extends Component { render () { const history = createBrowserHistory() return ( <Router basename="/"> <ConnectedRouter history={history}> <Suspense fallback={<Loader/>}> <Switch> <Route exact path="/" component={Main} /> <Route path="/admin" render={(props) => <RouteAdmin {...props} />}/> <Route path="/cabinet" component={props => <Cabinet {...props} />}}/> <Route path="/" component={() => <div>page not found</div>} /> </Switch> </Suspense> </ConnectedRouter> </Router> ) } } if (document.getElementById('app')) { ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.getElementById('app') ) } 

Usando React.lazy hacemos una carga lenta de componentes React.lazy está disponible a partir de la versión 16.6: React. Carga perezosa. El elemento Suspense está manejando la carga de componentes.

AdminModule solo puede ser descargado por un usuario autorizado, para esto utilizamos el componente RouteAdmin:

./RouteAdmin.js
 const NotAccess = (props) => { return ( <div> <h1 className="text-danger"> </h1> </div> ) } export default class RouteAdmin extends Component { constructor (props) { super(props) this.state = { component: null } } componentDidMount () { axios.post('/admin').then(data => data.data).then(data => { if (data.auth === true) { const Admin = React.lazy(() => import('./moduleAdmin/Index')) this.setState({component: Admin}) } else { this.setState({component: NotAccess}) } }) } render () { const Component = this.state.component return ( <Route path="/admin" {...this.props} render={this.state.component}/> ) } } 

Implementación del módulo


Archivo principal: agregar rutas de módulo

./moduleAdmin/Index.js
 export default class IndexComponent extends Component { constructor (props) { super(props) } render () { return ( <> <Route to="/admin/Profiles" component={Profiles} /> ... </> ) } } 

./moduleAdmin/pages/Profiles.js
 class Profiles extends Component { componentDidMount() { this.props.getInfo() } render() { if (this.props.loading === Process.Start) { return <Loader /> } if (this.props.loading === Process.Success) { return ( <div> <h1>Profiles</h1> </div> ) } return null } } const mapStateToProps = (state) => { return { loading: state.profiles.loading } } const mapDispatchToProps = (dispatch) => { return { getInfo: () => dispatch(getInfo()) } } export default connect( mapStateToProps, mapDispatchToProps )(Profiles) 

Crea un reductor


Lo registramos de inmediato en la tienda:

./moduleAdmin/redux/profile.js
 const Process = { Start: 0, Success: 1, Error: 2 } export const getInfo = () => { return (dispatch) => { dispatch({ type: PROFILES_GET_START }) axios.post('/news').then((data) => { dispatch({ type: PROFILES_GET_SUCCESS, payload: data.data }) }).catch(e => { dispatch({ type: PROFILES_GET_ERROR, payload: e }) }) } } const initialState = { error: null, loading: null, data: null } const reducer = (state = initialState, action) => { switch (action.type) { case PROFILES_GET_START: { return { ...state, loading: Process.Start } } case PROFILES_GET_SUCCESS: { return { ...state, loading: Process.Success, data: action.payload} } case PROFILES_GET_ERROR: { return { ...state, loading: Process.Error, error: action.payload } } default: { return state } } } reducerRegistry.register('profiles', reducer) 

Espero que mi artículo ayude en la implementación de su proyecto, y sus comentarios ayudarán a mejorar el mío.

Source: https://habr.com/ru/post/453294/


All Articles