-
-
Save c-lliope/93144c655eb5b635e471fdf4808f79fd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I'm working on a way to connect data to a user interface | |
in a way that is flexible, | |
yet still easy for end-users to work with. | |
This has been one of the biggest challenges for me. | |
## References: | |
* https://hackernoon.com/how-to-decouple-state-and-ui-a-k-a-you-dont-need-componentwillmount-cc90b787aa37 | |
* https://webpack.js.org/guides/code-splitting/ | |
```javascript | |
@action visitBlogPostPage(params) { | |
this.currentView = { | |
page: "blog", | |
post_id: 2, | |
} | |
} | |
@action visitAboutPage(params) { | |
this.currentView = { | |
component_name = params.page_name | |
page: fromPromise(import(component_name)) | |
} | |
} | |
@action signIn(params) { | |
// Parameters: { user_name: "foo", password: "bar" } | |
this.currentUser = fromPromise( serverSignIn(params) ) | |
this.currentView = { page: "home" } | |
} | |
@action someUserAction(params) { | |
this.currentView = { | |
component: fromPromise( | |
import("some-id-of-a-webpack-component-to-dynamically-load") | |
) | |
params, | |
data: fromPromise( | |
this.isAuthenticated | |
? this.fetch(`/json/${params}.json`) | |
: Promise.reject("Authentication required") | |
) | |
} | |
} | |
``` | |
Dynamically import the component | |
```javascript | |
function getComponent() { | |
return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => { | |
var element = document.createElement('div'); | |
var _ = _.default; | |
element.innerHTML = _.join(['Hello', 'webpack'], ' '); | |
return element; | |
}).catch(error => 'An error occurred while loading the component'); | |
} | |
getComponent().then(component => { | |
document.body.appendChild(component); | |
}) | |
``` | |
```javascript | |
import React from 'react'; | |
import { observer } from 'mobx-react'; | |
export const App = observer(({ store }) => ( | |
<Layout> | |
{ renderCurrentView(store) } | |
Current user: | |
{ store.isAuthenticated ? store.currentUser.name : "unknown user" } | |
</Layout> | |
)) | |
function renderCurrentView(store) { | |
const view = store.currentView; | |
switch (view.component.state) { | |
case "pending": | |
return <h1>Loading document.. { view.documentId }</h1> | |
case "rejected": | |
return <Error error={view.document.reason} /> | |
case "fulfilled": | |
switch (view.data.state) { | |
case "pending": | |
return <h1>Loading document.. { view.documentId }</h1> | |
case "rejected": | |
return <Error error={view.document.reason} /> | |
case "fulfilled": | |
return ( | |
React.createElement(view.component.value, { params, data: view.data.value }) | |
) | |
} | |
} | |
} | |
const Document = observer(({ view, store }) => { | |
if (!store.isAuthenticated) | |
return <Login store={store} afterLogin={() => store.showDocument(view.documentId)} /> | |
switch (view.document.state) { | |
case "pending": | |
return <h1>Loading document.. { view.documentId }</h1> | |
case "rejected": | |
return <Error error={view.document.reason} /> | |
case "fulfilled": | |
return ( | |
<div> | |
<button onClick={() => store.showOverview()}>Overview</button> | |
<h1>{ view.document.value.name }</h1> | |
<p> { view.document.value.text }</p> | |
</div> | |
) | |
} | |
}) | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment