Skip to content

Instantly share code, notes, and snippets.

@cdeutsch
Last active September 26, 2019 19:15
Show Gist options
  • Save cdeutsch/744b08b3609c5eb0d60dc59cbeec56df to your computer and use it in GitHub Desktop.
Save cdeutsch/744b08b3609c5eb0d60dc59cbeec56df to your computer and use it in GitHub Desktop.
Isomorphic Async Proposal
// UserStore.ts
//
// This is the code you write and is executed on the Node.js server side.
// The decorators can be used to automatically turn it into Express routes.
//
// Pretty much already exists using `routing-controllers` NPM
@Route('/api/users')
export class UserStore {
@Get('/')
public static async getAll() {
return db.users.find();
}
@Post('/')
public static async add(user) {
const newUser = db.users.add(user);
return newUser;
}
@Get('/anything')
public static async doAnything() {
// Do some random async task to sync user data.
}
}
// UserStore.ts
//
// A transformer like TypeScript, Babel, or Webpack will transform the "real" UserStore.ts into:
export class UserStore {
public static async getAll() {
return await axios.get('/api/users');
}
public static async add(user) {
return await axios.post('/api/users', user);
}
public static async doAnything() {
return await axios.get('/api/anything');
}
}
// Isomorphic React Component that can be re-used server and browser side:
export class UsersPage extends React.Component {
// Executed server side by next.js to populate initial data:
// https://nextjs.org/docs#fetching-data-and-component-lifecycle
static async getInitialProps({ req }) {
const users = await UserStore.getAll();
return { users: users };
}
constructor(props: any) {
super(props);
this.state = {
users: props.users
};
}
render() {
return (
<div>
<ul>
{this.state.users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
<button onClick={this.onClick}>Add random user</button>
</div>
);
}
onClick = async () => {
// calls the frontend version of
await UserStore.add({
name: randomNamePicker()
});
this.setState({
users: [...users, user]
})
}
}
// Server.ts
// Inspired by `routing-controllers`
// https://github.com/typestack/routing-controllers#example-of-usage
import { useExpressServer } from 'isomorphic-async';
import { UserStore } from './UserStore';
const app = express();
useExpressServer(app, {
routes: [UserStore],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment