Code Monkey home page Code Monkey logo

deku's Introduction

Deku

version version js-standard-style npm downloads discord

Deku is a library for rendering interfaces using pure functions and virtual DOM.

Instead of using classes and local state, Deku just uses functions and pushes the responsibility of all state management and side-effects onto tools like Redux. It also aims to support only modern browsers to keep things simple.

It can be used in place of libraries like React and works well with Redux and other libraries in the React ecosystem.

Deku consists of 5 modules packaged together for convenience:

  • element: Create virtual elements.
  • diff: Compute the difference between two virtual elements. You can use this if you're creating a custom renderer.
  • dom: Create DOM elements from virtual elements and update them using the result of a diff. You'll only use this directly if you're building your own app creator.
  • string: Render a HTML string from virtual elements.
  • createApp: Kickstart an app for the browser.

Installation

npm install --save deku

We support the latest two versions of each browser. This means we only support IE10+.

Sauce Test Status

Example

/** @jsx element */
import {element, createApp} from 'deku'
import {createStore} from 'redux'
import reducer from './reducer'

// Dispatch an action when the button is clicked
let log = dispatch => event => {
  dispatch({
    type: 'CLICKED'
  })
}

// Define a state-less component
let MyButton = {
  render: ({ props, children, dispatch }) => {
    return <button onClick={log(dispatch)}>{children}</button>
  }
}

// Create a Redux store to handle all UI actions and side-effects
let store = createStore(reducer)

// Create an app that can turn vnodes into real DOM elements
let render = createApp(document.body, store.dispatch)

// Update the page and add redux state to the context
render(
  <MyButton>Hello World!</MyButton>,
  store.getState()
)

Documentation

You can read the documentation online.

License

The MIT License (MIT) Copyright (c) 2015 Anthony Short

deku's People

Contributors

aeosynth avatar alepop avatar anthonyshort avatar archywillhe avatar bcinman avatar boopathi avatar call-a3 avatar chrisbuttery avatar dominicbarnes avatar dylanpiercey avatar gillstrom avatar greenkeeperio-bot avatar joedski avatar josepedrodiassky avatar kesla avatar kohei-takata avatar kvnneff avatar lancejpollard avatar olivierlacan avatar rivergrimm avatar rstacruz avatar seanstrom avatar stevenhauser avatar struckm avatar svnm avatar tejasmanohar avatar tel avatar voronianski avatar xdissent avatar yomguithereal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deku's Issues

Decouple ElementNode ?

This is awesome!

I don't know if you thought about it, but just thinking out loud here...

I think it would be awesome if ElementNode was it's own thing, that is an abstraction above HTMLElement and can be used to interact directly with Dom / Deku, that way it might be possible to re-use component/* stuff.

For example component/classes accepts an object and sets .className, there are lots of other components that do this, so it might be cool to have an abstract element that has the same API as HTMLElement.

thoughts?

cc @anthonyshort @lancejpollard

Make html escaping the default

It's super easy to forget to escape stuff to prevent XSS attacks. For example, if you allow users to enter some input into a textarea, and then you show that content somewhere in your app outside the textarea (even in multiple places), it's very easy to not realize it needs to be escaped.

So it would be a lot safer if it was the default :)

Basically it takes just using https://github.com/component/escape-html to escape any text node.

text = escape(text);

This will prevent a user from, for example, entering this into a text input:

hello <img src=x onerror="alert('i gonna steal yo cookies')">

add `debug` so it's easy to figure out where things go wrong

When building components, you may forget to put a property somewhere, or things like that, but then an error happens in the tree traversal. Then it's kinda hard to figure out what went wrong. I know you were mentioning something like this:

https://cldup.com/SyROO75I6M-600x600.png

discussion: replace setState with a setter

this.setState comes from React-land and to me always has felt a little clunky. Wouldn't it be neat if instead of using this.setState, state would be exposed as a getter / setter. The syntax would then become:

// react style
onClick() {
  this.setState({ clicked: true });
}

// getter / setter
onClick() {
  this.state = { clicked: true };
}

To my knowledge get / set is optimized by V8 (and probably other engines too), so performance shouldn't be noticeably impacted.

By no means am I saying that this.setState() is bad, but I figured it'd be cool to think about alternative syntaxes that require less learning. If this is something you like, I can write a PR that implements this. Hope this is helpful. Thanks!

Adding Animation

WIP

We've been thinking about how animation should work with components. Animation properties are basically another form of state, but it's cumbersome to store that stuff in state. Things like x and y position are a different kind of state. We'd like to be able to include it all in the serialized state too.

We could implement animation in a couple of ways...

  1. Using style tweens with easing and duration
  2. Using a physics library like Impluse.js

Here's an example using an API similar to Impluse

var MyComponent = component({
  afterMount: function(el){
    var position = getPosition(el); 
    this.translate()
      .spring({ tension: 100, damping: 10 })
      .from(position.x, position.y)
      .to(100, 100)
      .start();
  }
});

This would start another requestAnimationFrame loop on the component separate from the virtual DOM loop. This lets us avoid needing to do virtual tree diffing just to update some element animated properties.

If we provide a done method to beforeUnmount we could easily animate an element out:

var MyComponent = component({
  beforeUnmount: function(el, state, props, done){
    var stats = getPosition(el); 
    var position = this.translate()
      .spring({ tension: 100, damping: 10 })
      .from(stats.x, stats.y)
      .to(100, 100)
      .start();
    var opacity = this.fade(1, 0)
       .accelerate(100)
       .start();
    Promise.all([position, opacity], done);
  }
});

This is kind of long, but it's not overly abstract on purpose. We could make this into a plugin, or you could just use another library entirely. We'd just need to make sure whatever library it was played nicely with the updates from the virtual DOM.

Use Matt-Esch/virtual-dom

This module could benefit a lot from the ecosystem and work done around virtual-dom. It'd be nice to see the vdom stuff separated out so this is just a component/view implementation.

Better errors when empty modules are used

In ES6, when you import something and that something doesn't exist, it just gives you a blank object. This is pretty annoying because Deku will see that as a div because that's the default.

We should throw an error if a blank object is used as a component and give a helpful message like "That object isn't a component. Did you import the module correctly?"

Automatically create release in CI

Using Circle we can automatically create a release so that people who use globals (or don't use Duo or npm) so they can download it.

We want it to create the release whenever a new tag is pushed up to master.

Deku & Components

I was thinking about web components, and I had a small thought..

Application logic vs Component logic

Components should manage user interaction, clicks, drags, visual reaction.
Applications know not of clicks, they have two functions...

  1. Deal data: manage state, set authentication headers, model logic and transforms n' stuff.
  2. page navigation & component lifecycles & compositing views

Scatter not thine top level into thine bottom level!

Manage not thine pristine components as you would HTML with jQuery!

Thoughts on how this applies to Deku?

Moving diffing to virtual DOM

The diffing of the trees should be moved to the virtual dom module, which would return an array of changes to apply the to the element in the HTMLRenderer. We can't use another diffing module because of the unique way we're handling components.

SVG support

I believe svg elements require document.createElementNS instead of the usual document.createElement. Is this something deku would want to support?

Perhaps a domsvg method to supplement the dom method? Although ideally it would be invisible to the user and work with the existing dom method. d3 handles this duality somehow.

Here's an example:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<script src="lib/deku.min.js"></script>
</head>
<body>
<!-- <svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"></circle>
</svg> -->
<script>
component = deku.component;
dom = deku.dom;

var App = component({
  render: function(props, state) {
    dom('svg', { height: '100', width: '100' }, [
      dom('circle', {
        cx: '50',
        cy: '50',
        r: '40',
        stroke: 'black',
        'stroke-width': '3',
        fill: 'red'
      })
    ]);
  }
});
App.render(document.querySelector('body'));
</script>
</body>
</html>

Set default props

What are your thoughts on implementing something like initialProps?

initialProps() {
  return {
    ...
  };
}

Unable to access sources after the component is re-rendered

@lancejpollard

Here's an example demonstrating this:

var app = tree(<App/>);
app.set('hello', 'world');
render(app, document.body);

You can access the 'hello' source from within the App component the first time render is called. However, any time render is called after that, you can no longer access the 'hello' source from within the App component.

Input tabbing

I noticed something earlier, when two inputs are next to each other, tabbing to the next wasn't natural.

Here's a RequireBin that emulates what I mean. Type in the left one, then try to tab to the other.

Parent component setState inside passed handler to child

The lack of docs leads me to investigation of proper way to pass function handlers from container component to pure components.

My example

I have a higher-order container element which handles state and passes necessary props to "pure" state-less components:

/** @jsx deku.dom */

import deku from 'deku';

let Button = {
    handleClick(e, component) {
        e.preventDefault();

        let { playing, onToggle } = component.props;

       // do smth internally..
       // but I cannot pass setState from parent here..
       onTogglePlay && onTogglePlay(e, component);
    }, 

    render(component) {
        const { props } = component.;

        return (
            <button onClick={this.handleClick}>
                {props.playing ? 'Pause' : 'Play'}
            </button>
        );
    }
};

let Container = {
    initialState() {
        return {
            playing: false
        };
    },

    handleClick() {
         // I need to set `state` of Container here..
    },

    render(component) {
        let { state } = component;
        return (
            <div>
                <div>Some widget content</div>
                <Button playing={state.playing} onToggle={this.handleClick} />
            </div>
        );
    }
};

let app = deku.scene(
     <Container someProp="someData" />
);

deku.render(app, document.getElementById('app'));

As you see the problem is that I cannot take setState function from container inside passed handler.

I saw something similar in this example - https://github.com/segmentio/deku/blob/master/examples/todo/index.js#L18 Does it mean I need to use app.set with source on pure components?

decoupling components from context to enable async flows

I've been playing with deku this weekend, and though I'm liking it a lot, I've ran into a few limitations. Internally it appears properties are mutated in one of three ways:

  1. By calling a function that returns a value (e.g.
    component().prototype.render()).
  2. By calling functions bound to the scope (e.g. this.setState()).
  3. By mutating function arguments (state, props).

This isn't much of a problem if you're using deku in a OOP way, but if you try to deviate from the model (for example by extending it with event emitters) this becomes problematic. There's been talk of stopping to [rely on this to mutate state (https://github.com//issues/37), but I'd like to suggest decoupling property mutation from the context even further to make all sorts of async flows possible.

An example for the render property:

// OOP component
var button = deku.component()
button.prototype.render = function (props, state) {
  return deku.dom('button', state.text)
}

// decoupled component
var button = deku.component()
button.prototype.render = function (props, state, node) {
  node = deku.dom('button', state.text)  
}

The implementation of the above example would be completely backwards compatible, and plays well with event emitters. Would you be willing to accept patches that normalize the mutation of component properties? Thanks!

Value from inputs and communication to parent components

What is the best technique to implement a clichรฉ 'edit button'?

The code below shows a name and an edit button. When the button is pressed the view is switched out with a Editor component - an input field and save button. How does this other component communicate back the results of the edit, or cancel the edit?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <script src="deku/deku.min.js"></script>
  </head>
  <body>
    <script>
      var component = deku.component;
      var dom = deku.dom;

      var Editor = component({
        initialState: function(props) {
          return { value: props.value };
        },
        save: function(e, props, state) {
          // How do I get the value from the input?
          // How do I send it to App?
        },
        render: function(props, state) {
          return dom('div', [
            dom('input', { type: 'text', value: state.value }),
            dom('button', { onClick: this.save }, 'save')
          ]);
        }
      });

      var App = component({
        initialState: function(props) {
          return {
            name: props.name
          };
        },
        edit: function(e, props, state) {
          return this.setState({
            editing: true
          });
        },
        render: function(props, state) {
          if (state.editing) {
            return Editor({ value: state.name });
          } else {
            return dom('div', [
              state.name, dom('button', { onClick: this.edit }, 'edit')
            ]);
          }
        }
      });

      var body = document.querySelector('body');
      var scene = App.render(body, { name: 'Tom' });
    </script>
  </body>
</html>

Use Immutable State

We'll eventually move all of the state on entities into the scene in an immutable object using Immstruct.

Context

We could potentially send through a view or context object to the component hooks that holds the props, state, element, previous state, channels etc. on it. It could also have a .setState method.

This will pull all state off the component and allow the hooks to be easier to setup. This should be it's own class that we expose so people can easily create them for testing components.

lifecycle events

As mentioned in the roadmap (#3), what would the syntax for lifecycle events look like? Is it the goal to achieve event parity with React?

Trouble rendering component at the root of a tree

From what I can tell, I can only change the root tag once. After it is updated the first time it fails to update afterward. Here is a plunkr that reproduces the behavior I'm seeing: http://plnkr.co/edit/kOsqpnJ6v4vKLnlDYUtt?p=preview

  1. click the login button
  2. click the logout button
  3. observe the error message in the console about TypeError: Cannot read property 'insertBefore' of null

It seems that the root of the tree is no longer related to the parent element, but I can't seem to wrap my head around why...

Let me know if I can help!

Key diffing

Just like React, using key should optimize the diff. Already started working on this, it's not too hard if we leverage one of the existing array diffing modules out there.

Replace event handlers on re-render?

So if you have this:

var Page = component(function(props, state){
  var error = state.error;
  var self = this;

  function createError() {
    self.setState({ error: 'An error at ' + new Date });
  }

  function logError() {
    console.log(error);
  }

  return dom('div', [
    div('div.foo', { onClick: createError }, 'Create error')
    dom('div.log', { onClick: logError }, 'Log error')
  ]);
});
  1. first time around: error == null
  2. second time after you click Create error: error == 'An error at (Date)'

However, that logError function doesn't seem to be replaced between set states. This means, any time you click Log error, it will print null.

So basically it seems Deku just needs to replace event handlers each time. Thoughts?

Event Delegation

Perhaps I'm just used to this working because I've spent too much time around ng-click and $.delegate, but shouldn't events bubble up from children to their parents?

Currently, I'm not seeing this behavior. Repro

  1. Active links are green, inactive are red
  2. clicking the link text, the link does not become active
  3. click the padding of the <li>
  4. since the handler is assigned to it, the <li> turns active

Is there a way to make this work without assigning click handlers to every element within the click zone?

Pull existing information from the DOM

Web components are interesting - an html element is rendered on the server, delivered to the browser where a script discovers the element, reads the information and adds behaviour. Deku could render the element on the server and attach to the element in the browser afterwards for behaviour.

At the moment I presume it does not attach to existing elements because deku has no reference to the element. Perhaps this could be changed?

Github have an example where they render a custom time element which is picked up in the browser and localised, and perhaps continually updated.

Is this behaviour something deku might support?

Something hacky could be implemented on afterMount to find a sibling element but that does not seem elegant.

The benefit is that the data can be delivered in the page instead of through an additional JSON request. Even if the DOM text is JSON that is parsed and merged with props I think it's a nice addition.

require setState instead of passing it through context

Hey, once again, awesome job you guys have done here with deku! Really impressed.

Just a suggestion that has come to my mind. What do you guys think of requiring setState as a simple utility function instead of passing it to the component's context? I think the component() constructor is overloaded with 4 arguments. This would make the function setState() more transparent.

The function would set the state given a component and the new state. Like it is now, except not partially applied.

Basically just switching

export function afterUpdate (component, prevProps, prevState, setState) {
  let {props, state} = component
  if (!state.clicked) {
    setState({ clicked: true })
  }
}

to

import { setState } from 'deku';

export function afterUpdate (component, prevProps, prevState) {
  let {props, state} = component
  if (!state.clicked) {
    setState(component, { clicked: true })
  }
}

It seems like this is not possible though, since the entire entity is needed and not just entity.component.

v1.0

Here's an on-going list of what needs to be done to get it to a v1.0

Next

  • key property diffing
  • entity.setProps should merge instead of replacing
  • cross-browser tests
  • working TodoMVC example
  • Documentation

Later

  • Immutable props/state with cursors
  • Serializable state atom
  • move el to props.el instead of passing it in
  • move virtual dom to it's own module
  • Return a promise from setState
  • move diffing to virtual-dom
  • diff should return an array of changes
  • mount using pre-rendered DOM elements (matched using a sha)
  • performance testing using matcha (https://github.com/logicalparadox/matcha)

Done

  • Bower support
  • Globals support
  • Tests for propsChanged
  • Emit events on Component lifecycle
  • Add test for component.invalidate
  • add support for adding classes within the selector string eg. dom('div.foo.bar')
  • events/interaction system
  • add child support to components via props.children
  • renderToString for server rendering
  • Browserify support
  • Support for attribute values as objects... class: { blah: true, bloo: false }
  • Support for styles as object... styles: { textAlign: left; }
  • npm support
  • batched rendering
  • comprehensive diffing
  • managed component lifecycle + rendering to prevent unnecessary rendering
  • complete component lifecycle event hooks (beforeUpdate, afterUpdate etc)

@lancejpollard

Flatten entity structure

At the moment, we have all the entities in a nested object, eg. entity.children. The way this should work is that we'd store all entities on the scene by id and then an entity (or the renderer) handles the structure, by storing references like:

{
  "0.1.0": "entityIdHere",
  "1.5.3": "entityIdHere"
}

Then the renderer can just use that instead. The reason for this change is that it would be hard to implement a scene-level state graph using immutable data. If we implement #43 then all the component state will be stored on a model, that model will map to a entity on the scene, and that entity will have children.

Decouple all the things!

license

There's no license included nor a license in the README. It might be nice to have (:

Collect code sketches in an ./examples folder

As we're playing around with ideas on different implementations of things, and seeing how to write components like the menu or button, or anything else, would be cool if we collected all that stuff into an ./examples folder so down the road when we get some real docs we have a solid set of stuff to use :)

Even if the examples are just rough ideas (like many of the issues have example sketches), we can perhaps put them into ./examples/sketches or something, so you know they aren't real examples. Something along those lines perhaps. Like this is one snippet from another issue:

return App(null, [
  dom('div', null, [
    Button()
  ]),
  DialogController(),
  TooltipController()
])

What is the difference between state and props?

I'm really liking this so far. Very clean and simple. Everything is fairly understandable except I think state and props.

What is the difference between state and props and when would I use one over the other?

Looking at the examples I can see that props is being altered through scene.setProps. Is this the only way to manipulate props?

State and props seem to be individual per component. How do I pass information to any child components? Through props.children? What is props.children?

Also how does deku fit with ripple.js? Is it a successor?

And my last question, should I be using deku now? And what is your goal for deku?

Coming from reactive

Hi, does deku's compare with component/reactive? Does utilization of virtual doms improve overall performance?

Add development mode

It would be nice if we could know if the user is running in a 'dev' mode so we could output more messages and throw more errors when things aren't setup right. This would be handy for things like prop validation.

var env = require('env');
if (env.development) throw Error('Doh!');

Hoepfully there is some browser/node module out there for picking things up from window. Then all they'd need to do is set window.DEV = true or something.

Publish on npm / npm module name

Apparently deku isn't published to npm. If you want to use Deku with Browserify (see also #17) it would be nice if deku itself was on npm. The name deku is taken already though. Would you be interested in publishing it to npm possibly under a new name?

Some names that are available on npm:

  • deku-ui
  • segmentio-deku
  • component-deku

I also saw a (joking) suggestion to change the name, but I'm not sure if this is something you guys would want to do.
Thanks!

Props equals null when state changes

If a components state changes, but not the props, the props is equal to null on the next render.

this.props = nextProps || this.props;

Need to write a test for this.

Error when the propType isn't specified

When using the set function, if the propType isn't specified this error occurs.

Uncaught TypeError: connections[name] is not a function
const App = {
  propTypes: {
    foo: {
      source: 'foo'
    }
  },

  render(comp) {
    let {props} = comp;
    let {foo} = props;

    return (
      <div>
        {foo || 'App'}
      </div>
    );
  }
}

const app = tree(<App/>);

render(app, document.body);

app.set('foo', 'bar');

Demo.

Queue up sources data to prevent error

If you set sources but haven't yet created a component that uses it, it will error:

Uncaught TypeError: connections[name] is not a function

Maybe it just uses a blank function initially or something.

Make components easier to compose

Currently to compose Components you need to do this:

var App = component({
  render(dom, state, props) {
    return dom('div', { class: 'App' }, [
      dom(ButtonComponent, { text: props.buttonText })
    ]);
  }
});

But we could make it this:

var App = component({
  render(dom, state, props) {
    return dom('div', { class: 'App' }, [
      ButtonComponent({ text: props.buttonText })
    ]);
  }
});

By making a component return dom(ButtonComponent, { text: props.buttonText }) if it is called without new. It's a little magic but it does make it nicer to build the trees

Communicating between components

@lancejpollard

We were chatting the other day about how to communicate between components in a decoupled way when there are things like a dialog or tooltips that within the tree.

return App(null, [
  dom('div', null, [
    Button()
  ]),
  DialogController(),
  TooltipController()
])

Where ChildComponent wants to create a dialog or tooltip. How would this work? One way we thought it could be neat would be to have a listen and send method on components. Components all have access to the Scene - the top-level loop - indirectly through the Entity. We could use the scene as an event emitter to communicate between components in the tree.

This means we don't need to pass things all the way down the tree if all the intermediate objects don't care about it. React is handling this with Contexts which is a little crazy. I think it can be simpler than that.

var DialogController = component({
  afterMount: function(){
    var self = this;
    this.listen('create dialog', function(nodes){
      this.setState({ content: nodes });
    });
  },
  render: function(dom, state){
    if (state.content) {
      // if there's content, create the dialog
    }
}); 

var Button = component({
  onClick: function(e){
    this.send('create dialog', 'Hi there!');
  },
  render: function(dom){
    return dom('a', { 'on-click': this.onClick }), 'Show Dialog');
  }
});

Events are decoupled so it's still easy to test both of them - scene.emit('create dialog', 'test'). We don't want to give direct access to the scene on components so that they don't try and store state on it.

prop declaration/validation

var Button = component()
  .prop('onClick', { type: 'function', required: true })
  .prop('text');

If you send a property through that isn't declared, it will show a warning in the console in dev mode.

Warning: Undefined prop `text` set on component `Button`
Warning: Invalid type 'boolean' for prop `text` on component `Button`. Expected 'string'

It could be a plugin too:

Button.use(validation())

Alternative syntax for class-style:

var Button = component({
  props: {
    'text': { type: 'string', required: true }
  }
});

How to query for current state?

It looks like a component can't query for state but can save state against this instead. The below example is a number that increments every second. The function running from setInterval can't query for changed state, so can only use a variable previously saved against this.

Is there a better way to implement this example?

Additionally there is no way to invalidate state without passing a new variable to setState. I understand that render should only rely on state so that makes sense, however in this example I'm having to use another variable to copy the state.

Taken to the extreme it might be easier to always make a copy of props and state to this on every update, however I suspect there is a good reason why this isn't already available in the API.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<script src="lib/deku.js"></script>
</head>
<body>
<script>
var component = deku.component;
var dom = deku.dom;

Seconds = component({
  initialState: function(props) {
    this.value = props.value;
    return { value: this.value };
  },
  tick: function() {
    this.value++;
    this.setState({ value: this.value });
  },
  afterMount: function(el, props, state) {
    this.interval = setInterval(this.tick.bind(this), 1000);
  },
  beforeUnmount: function() {
    if (this.interval != null) {
      clearInterval(this.interval);
    }
  },
  render: function(props, state) {
    return dom('div', state.value.toString());
  }
});

Seconds.render(document.querySelector('body'), { value: 0 });
</script>
</body>
</html>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.