Skip to content

Instantly share code, notes, and snippets.

@lantiga
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lantiga/8984978 to your computer and use it in GitHub Desktop.
Save lantiga/8984978 to your computer and use it in GitHub Desktop.
ki port of the official React tutorial: http://facebook.github.io/react/docs/tutorial.html. See ki at https://github.com/lantiga/ki.
ki -o react_ki.out.js react_ki.js
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.8.0.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script src="mori.js"></script>
</head>
<body>
<div id="content"></div>
<script src="react_ki.out.js"></script>
</body>
</html>
// A few macros for writing React components concisely using s-expressions instead of JSX
ki macro (defcomp $name $render_body)
(def $name ((js React.createClass)
{$ 'render' (fn [] $render_body)}))
ki macro (defcomp $name {$kv ...} $render_body)
(def $name ((js React.createClass)
{$kv ... 'render' (fn [] $render_body)}))
ki macro (dom $tag {$kv ...} $children ...)
((js React.DOM.$tag) {$kv ...} $children ...)
ki macro (dom $tag $children ...)
((js React.DOM.$tag) (js {}) $children ...)
// Tutorial code starts here
// The CommentBox component just does a fake async request using setTimeout.
// State is stored in a persistent data structure within React state in CommentBox.
// In another version global state could be moved to an atom using atom callbacks
// to trigger a re-rendering.
ki require core
ki (do
(def data [{:author "Pete Hunt" :text "This is one comment"}
{:author "Jordan Walke" :text "This is another comment"}])
(defcomp Comment
(dom div {$ :className 'comment'}
(dom h2 {$ :className 'commentAuthor'} this.props.author)
this.props.children))
(defcomp CommentList
(dom div {$ :className 'commentList'}
(clj_to_js
(map (fn [comment i]
(Comment {$ :author (get comment :author)} (get comment :text)))
this.props.data))))
(defcomp CommentForm
{$ :handleSubmit
(fn []
(let [author (js this.refs.author.getDOMNode().value.trim())
text (js this.refs.text.getDOMNode().value.trim())]
(this.props.onCommentSubmit {:author author :text text})
(js this.refs.author.getDOMNode().value = '')
(js this.refs.text.getDOMNode().value = '')
false))}
(dom form {$ :className 'commentForm' :onSubmit this.handleSubmit}
(dom input {$ :type 'text' :placeholder 'Your name' :ref 'author'})
(dom input {$ :type 'text' :placeholder 'Say something...' :ref 'text'})
(dom input {$ :type 'submit' :value 'Post'})))
(defcomp CommentBox
{$ :getInitialState
(fn []
{$ :data [{:author "Pete Hunt" :text "This is one comment"}]})
:componentWillMount
(fn []
(setTimeout (fnth [] (this.setState {$ :data data})) 1000))
:handleCommentSubmit
(fn [comment]
(this.setState {$ data (conj this.state.data comment)}))}
(dom div {$ :className 'commentBox'}
(dom h1 'Comments')
(CommentList {$ :data this.state.data})
(CommentForm {$ :onCommentSubmit this.handleCommentSubmit})))
(React.renderComponent (CommentBox) (document.getElementById 'content'))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment