createModule({
home: '/',
login: '/login',
dashboard: {
path: '/dashboard',
module: createModule({
settings: '/settings',
myAccount: '/my-account',
}, {
Process: CamTwist [1578] | |
Path: /Applications/CamTwist/CamTwist.app/Contents/MacOS/CamTwist | |
Identifier: com.allocinit.CamTwist | |
Version: 3.4.3 (3.4.3) | |
Code Type: X86-64 (Native) | |
Parent Process: ??? [1] | |
Responsible: CamTwist [1578] | |
User ID: 501 | |
Date/Time: 2019-08-02 18:24:51.316 -0700 |
import { Box } from 'respond' | |
export function Items(props) { | |
return Box({ | |
style: { margin: 20, padding: 10 }, | |
children: [ | |
Item({ name: 'svelte' }), | |
Item({ name: 'react' }), | |
Item({ name: 'vue' }), | |
], |
const MyRespondModal = (props, state, actions) => ( | |
<Modal | |
visible={!!state.modalText} | |
text={state.modalText} | |
onClose={actions.cancel} | |
onSubmit={actions.confirm} | |
/> | |
) | |
const Modal = ({ visible, text, onClose, onSubmit }) => { |
export default createApp({ | |
components: { | |
App: (props, { location }) => { | |
const Component = location.components.list.ComponentWithHoistedDataDeps | |
return Component ? <Component /> : <Spinner /> | |
}, | |
}, | |
routes: { | |
LIST: { | |
path: '/list/:category', |
import { testGenerator } from 'respond-framework/test' | |
const routes = { | |
LOGIN: '/login', | |
SIGNUP: '/signup', | |
POST: '/post/:slug', | |
HOME: { | |
path: '/', | |
next: { | |
LOGIN: request => !!request.getState().cookies.existingUser, |
Respond Framework Walkthrough
Respond Framework is what happens if you build Redux & first-class concerns for routing into React, plus take a page from the traditional server-side MVC playbook when it comes to side-effects.
Here's a quick overview of the features and usage in Respond Framework.
Installation
Our Manifest
Below is our manifest which has the information of every route the app has. It's statically generated by our babel-plugin at compile time.
It has the absolute minimal amount of information necessary so that it's possible for any route to dispatch actions to any other route.
Since createScene()
generates action creators from simply our routesMap types/keys, that's all we need to generate ALL ACTIONS. Well, there is a few small edge cases, but you got the idea.
How we assign components to modules
This insures each component only can access the state from the module its part of.
- here's the intermediary data structure we generate in a single babel pass:
// implementation 1 | |
const load = (api) => async (req, next) => { | |
const { route, action } = req | |
const hasLoad = route && route.load | |
if (!hasLoad) return next() | |
const { components, reducers, chunks, ...res } = await route.load(req) || {} |