1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Add Cerebral example (#2976)

This commit is contained in:
Christian Alfoni 2017-09-23 16:30:22 +02:00 committed by Tim Neutkens
parent 4bd30c8713
commit 094bb1f7b9
9 changed files with 218 additions and 0 deletions

View file

@ -0,0 +1,24 @@
export default (props) => {
return (
<div className={props.light ? 'light' : ''}>
{format(new Date(props.lastUpdate))}
<style jsx>{`
div {
padding: 15px;
color: #82FA58;
display: inline-block;
font: 50px menlo, monaco, monospace;
background-color: #000;
}
.light {
background-color: #999;
}
`}</style>
</div>
)
}
const format = t => `${pad(t.getUTCHours())}:${pad(t.getUTCMinutes())}:${pad(t.getUTCSeconds())}`
const pad = n => n < 10 ? `0${n}` : n

View file

@ -0,0 +1,33 @@
import React from 'react'
import Link from 'next/link'
import { connect } from '@cerebral/react'
import { state, signal } from 'cerebral/tags'
import Clock from './Clock'
export default connect({
lastUpdate: state`clock.lastUpdate`,
light: state`clock.light`,
mounted: signal`clock.mounted`,
unMounted: signal`clock.unMounted`
},
class Page extends React.Component {
componentDidMount () {
this.props.mounted()
}
componentWillUnmount () {
this.props.unMounted()
}
render () {
return (
<div>
<h1>{this.props.title}</h1>
<Clock lastUpdate={this.props.lastUpdate} light={this.props.light} />
<nav>
<Link href={this.props.linkTo}><a>Navigate</a></Link>
</nav>
</div>
)
}
}
)

View file

@ -0,0 +1,7 @@
export function startTimer ({clock}) {
clock.start('clock.secondTicked')
}
export function stopTimer ({clock}) {
clock.stop()
}

View file

@ -0,0 +1,16 @@
import {mounted, unMounted, secondTicked} from './signals'
import provider from './provider'
export default {
state: {
lastUpdate: 0,
light: false
},
signals: {
mounted,
unMounted,
secondTicked
},
provider
}

View file

@ -0,0 +1,26 @@
// milliseconds per second
const SECOND = 1000
let timer = null
export default (context) => {
context.clock = {
start (signalPath) {
const signal = context.controller.getSignal(signalPath)
function tick () {
const now = Date.now()
signal({now})
timer = setTimeout(tick, SECOND - (now % SECOND))
}
tick()
},
stop () {
clearTimeout(timer)
}
}
return context
}

View file

@ -0,0 +1,10 @@
import {set} from 'cerebral/operators'
import {state, props} from 'cerebral/tags'
import {startTimer, stopTimer} from './actions'
export const mounted = [
startTimer,
set(state`clock.light`, true)
]
export const unMounted = stopTimer
export const secondTicked = set(state`clock.lastUpdate`, props`now`)

View file

@ -0,0 +1,18 @@
{
"name": "with-cerebral",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"author": "",
"license": "ISC",
"dependencies": {
"@cerebral/react": "^2.1.0",
"cerebral": "^3.1.0",
"next": "^3.2.2"
}
}

View file

@ -0,0 +1,42 @@
import React from 'react'
import {Controller, UniversalController} from 'cerebral'
import Devtools from 'cerebral/devtools'
import { Container } from '@cerebral/react'
import Page from '../components/Page'
import clock from '../modules/clock'
export default class Counter extends React.Component {
static getInitialProps ({req}) {
const isServer = Boolean(req)
// On the server we prepare the state of the application. Since
// this is a synchronous state change we just use "setState", but
// you could do other async stuff here or even use "runSequence" to
// grab and set the initial state of the application using
if (isServer) {
const controller = UniversalController({modules: {clock}})
controller.setState('clock.lastUpdate', Date.now())
return { stateChanges: controller.getChanges() }
}
return {}
}
constructor (props) {
super(props)
// The controller will be instantiated for every page change and we only
// add the devtools if we indeed are running in the browser
this.controller = Controller({
devtools: process.env.NODE_ENV === 'production' || typeof window === 'undefined' ? null : Devtools({host: 'localhost:8787'}),
modules: {clock},
stateChanges: props.stateChanges
})
}
render () {
return (
<Container controller={this.controller}>
<Page title='Index Page' linkTo='/other' />
</Container>
)
}
}

View file

@ -0,0 +1,42 @@
import React from 'react'
import {Controller, UniversalController} from 'cerebral'
import Devtools from 'cerebral/devtools'
import { Container } from '@cerebral/react'
import Page from '../components/Page'
import clock from '../modules/clock'
export default class Counter extends React.Component {
static getInitialProps ({req}) {
const isServer = Boolean(req)
// On the server we prepare the state of the application. Since
// this is a synchronous state change we just use "setState", but
// you could do other async stuff here or even use "runSequence" to
// grab and set the initial state of the application using
if (isServer) {
const controller = UniversalController({modules: {clock}})
controller.setState('clock.lastUpdate', Date.now())
return { stateChanges: controller.getChanges() }
}
return {}
}
constructor (props) {
super(props)
// The controller will be instantiated for every page change and we only
// add the devtools if we indeed are running in the browser
this.controller = Controller({
devtools: process.env.NODE_ENV === 'production' || typeof window === 'undefined' ? null : Devtools({host: 'localhost:8787'}),
modules: {clock},
stateChanges: props.stateChanges
})
}
render () {
return (
<Container controller={this.controller}>
<Page title='Other Page' linkTo='/' />
</Container>
)
}
}