Think of your app in terms of states, not routes or components. Connect your components and just dispatch Flux Standard Routing Actions!
Rudy is the successor to redux-first-router. Compared to RFR, there are many new features, and some breaking changes. It is a work in progress. The basic features work, but there are still bugs and some features are incomplete.
Rudy is a library for creating a controller (as in Model View Controller) for redux based apps. It provides an abstraction for handling all the side effects and cross cutting concerns that tend to pollute React components and make apps difficult to understand and work with. Some of the things it can do:
This library can help you build an app where:
yarn add @respond-framework/rudy
// index.js // The entrypoint is mostly standard react-redux, just note the call to configureStore() and the last line. import React from 'react' import { connect, Provider } from 'react-redux' import ReactDOM from 'react-dom' import configureStore from './configureStore' import * as components from './components' // App component const App = ({ page }) => { const Component = components[page] return <Component /> } const ConnectedApp = connect(({ page }) => ({ page }))(App) // Redux setup const { store, firstRoute } = configureStore() function render() { ReactDOM.render( <Provider store={store}> <ConnectedApp /> </Provider>, document.getElementById('root'), ) } store.dispatch(firstRoute()).then(() => render())
// routes.js // Routes are centrally defined along with their paths, along with much more that is not shown here for simplicity. export default { HOME: '/', USER: '/user/:id', }
// pageReducer.js // A simple reducer maps path actions to component names. This makes it easy to dynamically import pages! const components = { HOME: 'Home', USER: 'User', NOT_FOUND: 'NotFound', } export default (state = 'Home', action = {}) => components[action.type] || state
// configureStore.js // Configures the router and inserts it into the Redux store. // Both arguments in the exported function are optional. import { applyMiddleware, combineReducers, compose, createStore } from 'redux' import { createRouter } from '@respond-framework/rudy' import routes from './routes' import page from './pageReducer' export default (preloadedState, initialEntries) => { const options = { initialEntries } const { reducer, middleware, firstRoute } = createRouter(routes, options) const rootReducer = combineReducers({ page, location: reducer }) const middlewares = applyMiddleware(middleware) const enhancers = compose(middlewares) const store = createStore(rootReducer, preloadedState, enhancers) return { store, firstRoute } }
// components.js // A few trivial components which can now access location and any params through Redux! import React from 'react' import { connect } from 'react-redux' // Home component const Home = ({ visitUser }) => { const rndUserId = Math.floor(20 * Math.random()) return ( <div> <p>Welcome home!</p> <button type="button" onClick={() => visitUser(rndUserId)}> {`Visit user ${rndUserId}`} </button> </div> ) } const ConnectedHome = connect( null, (dispatch) => ({ visitUser: (userId) => dispatch({ type: 'USER', params: { id: userId } }), }), )(Home) // User component const User = ({ goHome, userId }) => ( <div> <p>{`User component: user ${userId}`}</p> <button type="button" onClick={() => goHome()}> Back </button> </div> ) const ConnectedUser = connect( ({ location: { params } }) => ({ userId: params.id }), (dispatch) => ({ goHome: () => dispatch({ type: 'HOME' }) }), )(User) // 404 component const NotFound = ({ pathname }) => ( <div> <h3>404</h3> Page not found: <code>{pathname}</code> </div> ) const ConnectedNotFound = connect(({ location: { pathname } }) => ({ pathname, }))(NotFound) export { ConnectedHome as Home, ConnectedUser as User, ConnectedNotFound as NotFound, }
The source code for this example can be found here.
Also see:
The redux actions that Rudy synchronises with URLs have a particular shape and meaning.
const routes = { BLOB: { path: '/:namespace/:repo/blob/:ref/:path+', }, } const url = { url: '/respond-framework/rudy/blob/master/README.md?unused=test#the-flux-standard-routing-action-fsra', state: { invisible: '12345', }, } const action = { type: 'BLOB', params: { namespace: 'respond-framework', repo: 'rudy', ref: 'master', path: 'README.md', }, query: { unused: 'test', }, hash: 'the-flux-standard-routing-action-fsra', state: { invisible: '12345', }, } actionToUrl(action) == { url, state: { invisible: '12345' } } urlToAction({ url, state: { invisible: '12345' }) == action
Pull requests are welcome! See HACKING for some simple instructions for getting started if you want to make an improvement. More detailed documentation about development is available in the development docs directory.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4