<!doctype html><html data-reactid=".7dp7kc1c74" data-react-checksum="-1737566687"><head data-reactid=".7dp7kc1c74.0"><title data-reactid=".7dp7kc1c74.0.0">Qiming Weng</title><link rel="stylesheet" href="/style.css" data-reactid=".7dp7kc1c74.0.1"><link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" data-reactid=".7dp7kc1c74.0.2"><script src="//use.typekit.net/mak3sgg.js" data-reactid=".7dp7kc1c74.0.3"></script><script data-reactid=".7dp7kc1c74.0.4">try{Typekit.load();}catch(e){}</script><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.6/styles/github-gist.min.css" data-reactid=".7dp7kc1c74.0.5"><script type="text/javascript" data-reactid=".7dp7kc1c74.0.6">
						(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
					  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
					  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
					  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

					  ga('create', 'UA-7576029-2', 'auto');</script><meta name="viewport" content="initial-scale=1, maximum-scale=1" data-reactid=".7dp7kc1c74.0.7"></head><body data-reactid=".7dp7kc1c74.1"><div id="home-page" style="background-color:#0096d6;" data-reactid=".7dp7kc1c74.1.0"><header data-reactid=".7dp7kc1c74.1.0.0"><h1 data-reactid=".7dp7kc1c74.1.0.0.0">Qiming Weng</h1><h2 data-reactid=".7dp7kc1c74.1.0.0.1"><span data-reactid=".7dp7kc1c74.1.0.0.1.0">Chief Product Officer at </span><a href="https://edusight.co" target="_blank" data-reactid=".7dp7kc1c74.1.0.0.1.1">Edusight</a></h2><h3 data-reactid=".7dp7kc1c74.1.0.0.2">Designer, Developer</h3><div id="links" data-reactid=".7dp7kc1c74.1.0.0.3"><a class="fa fa-twitter" href="https://twitter.com/qiming" target="_blank" data-reactid=".7dp7kc1c74.1.0.0.3.0"></a><a class="fa fa-dribbble" href="https://dribbble.com/qiming" target="_blank" data-reactid=".7dp7kc1c74.1.0.0.3.1"></a><a class="fa fa-github" href="https://github.com/qimingweng" target="_blank" data-reactid=".7dp7kc1c74.1.0.0.3.2"></a><a class="fa fa-instagram" href="https://instagram.com/qiming" target="_blank" data-reactid=".7dp7kc1c74.1.0.0.3.3"></a></div></header></div><script id="initial-props" type="application/json" data-reactid=".7dp7kc1c74.1.1">{"path":"/","assets":{"main":"bundle.js"},"posts":[{"slug":"react-modal-dialog","title":"Modal Dialogs with ReactJS","subtitle":"How to create idiomatic modal dialogs with ReactJS using a technique called Portals","date":"2015-06-21T00:00:00.000Z","html":"<h2 id=\"the-problem\">The problem</h2>\n<p>Modal dialogs are a frequently used part of web interfaces. They alert you to very important events, they allow you to confirm very dangerous actions, they can be tooltips to give you more information about something.</p>\n<p>However, modal dialogs are very stateful. They are often presented as a reaction to something, and so this makes it hard to model in the traditional Flux model.</p>\n<p>Dialogs are also quite tricky because they have to behave in certain ways.</p>\n<h2 id=\"prerequisites\">Prerequisites</h2>\n<p>You should know react very well. It is helpful to know Flux, but we don&#39;t use it, and I only really discuss how that isn&#39;t enough to solve this problem.</p>\n<h2 id=\"react-js-goals\">React JS Goals</h2>\n<ol>\n<li>Use only react components to render modal dialogs</li>\n<li>Keep the dialog component code as close as possible to the component that wants the dialog opened</li>\n</ol>\n<h2 id=\"broader-dialog-goals\">Broader Dialog Goals</h2>\n<ol>\n<li>Close a dialog in response to the ESC key</li>\n<li>Close a dialog when clicking outside of its bounds</li>\n<li>If there are two or more dialogs, one on top of the other, close only the top dialog when responding to the keyboard or mouse</li>\n</ol>\n<h2 id=\"a-few-ways-to-solve-this-problem\">A few ways to solve this problem</h2>\n<p>There are actually a few ways to solve this problem</p>\n<p>The first way I thought of was to have a <code>&lt;ModalDialog&gt;</code> component at the root level. For example</p>\n<pre class=\"hljs\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">Root</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  render() {\n    <span class=\"hljs-keyword\">return</span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">html</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">head</span>&gt;</span>\n          ...\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">body</span>&gt;</span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">Application</span>/&gt;</span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">ModalDialogs</span> <span class=\"hljs-attribute\">dialogContent</span>=<span class=\"hljs-value\">{SomeStore.currentModalDialog}</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">body</span>&gt;</span>\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">html</span>&gt;</span>\n    )</span>\n  }\n}</pre><p>We would then use something like an app dispatcher to send it a message, and it would respond</p>\n<p>This particular approach didn&#39;t work for me for several reasons</p>\n<ol>\n<li>I&#39;m migrating a huge project to react, and there doesn&#39;t exist a root react instance</li>\n<li>Keeping a global modal dialog instance makes it difficult to do modal dialogs on top of modal dialogs<ul>\n<li>To do this, <code>SomeStore.currentModalDialog</code> would need to be an array</li>\n</ul>\n</li>\n<li>There would presumably be a giant switch statement somewhere and a <code>/dialogs/</code> folder where I keep all my dialog component files. In this model, the dialog logic is very far from the component that wants to show that dialog, and the distance makes me uncomfortable</li>\n</ol>\n<h2 id=\"what-i-wanted\">What I wanted</h2>\n<pre class=\"hljs\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">Button</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  state = {\n    showDialog: <span class=\"hljs-literal\">false</span>\n  }\n  showDialog = () =&gt; {\n    <span class=\"hljs-keyword\">this</span>.setState({\n      showDialog: <span class=\"hljs-literal\">true</span>\n    })\n  }\n  hideDialog = () =&gt; {\n    <span class=\"hljs-keyword\">this</span>.setState({\n      showDialog: <span class=\"hljs-literal\">false</span>\n    })\n  }\n  render() {\n    <span class=\"hljs-keyword\">return</span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">div</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">a</span> <span class=\"hljs-attribute\">onClick</span>=<span class=\"hljs-value\">{this.showDialog}</span>&gt;</span>This is a button<span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">a</span>&gt;</span>\n        {this.state.showDialog ?\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">ModalDialog</span> <span class=\"hljs-attribute\">onClose</span>=<span class=\"hljs-value\">{this.state.hideDialog}</span>/&gt;</span>\n        : null}\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">div</span>&gt;</span>\n    )</span>\n  }\n}</pre><p>In this model, I can stick <code>&lt;Button/&gt;</code> wherever I want, and it should open the dialog</p>\n<h2 id=\"how-to-get-this-to-actually-work-introducing-portals-\">How to get this to actually work... Introducing Portals!</h2>\n<p>Now that I knew what the syntax I wanted was, it was time to figure out how to actually make this work. This is when I discovered <a href=\"http://stackoverflow.com/questions/26787198/reactjs-modal-using-javascript-and-css\">portals</a> (or, some people call them layers, but tbh, portals sounds cooler).</p>\n<p>Here&#39;s what a portal looks like</p>\n<pre class=\"hljs\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">Portal</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  _target = <span class=\"hljs-literal\">null</span> <span class=\"hljs-comment\">// HTMLElement, a div appended to the body</span>\n  _component = <span class=\"hljs-literal\">null</span> <span class=\"hljs-comment\">// ReactComponent, mounted on the target</span>\n  static propTypes = {\n    onClose: PropTypes.func <span class=\"hljs-comment\">// This is called when the dialog should close</span>\n  }\n  componentDidMount = () =&gt; {\n    <span class=\"hljs-comment\">// Create a div and append it to the body</span>\n    <span class=\"hljs-keyword\">this</span>._target = <span class=\"hljs-built_in\">document</span>.body.appendChild(<span class=\"hljs-built_in\">document</span>.createElement(<span class=\"hljs-string\">'div'</span>));\n\n    <span class=\"hljs-comment\">// Mount a component on that div</span>\n    <span class=\"hljs-keyword\">this</span>._component = React.render(<span class=\"hljs-keyword\">this</span>.props.children, <span class=\"hljs-keyword\">this</span>._target);\n  }\n  componentDidUpdate = () =&gt; {\n    <span class=\"hljs-comment\">// When the child component updates, we have to make sure the content rendered to the DOM is updated to</span>\n    <span class=\"hljs-keyword\">this</span>._component = React.render(<span class=\"hljs-keyword\">this</span>.props.children, <span class=\"hljs-keyword\">this</span>._target);\n  }\n  componentWillUnmount = () =&gt; {\n    React.unmountComponentAtNode(<span class=\"hljs-keyword\">this</span>._target);\n    <span class=\"hljs-built_in\">document</span>.body.removeChild(<span class=\"hljs-keyword\">this</span>._target);\n  }\n  render = () =&gt; <span class=\"hljs-literal\">null</span> <span class=\"hljs-comment\">// Portals don't render anything themselves!</span>\n}</pre><p>What this portal does, is that when it is mounted, instead of rendering to its location within, for example, <code>&lt;Button/&gt;</code>, it will create a brand new <code>&lt;div&gt;</code> as the last child in <code>&lt;body&gt;</code>, and it renders its children on that new node, effectively piping the output from <code>&lt;Button/&gt;</code> to this new div in the body: hence, &quot;Portal&quot;.</p>\n<p>Let&#39;s revisit the <code>&lt;Button&gt;</code> class, here&#39;s what the render function might look like now...</p>\n<pre class=\"hljs\">render() {\n  <span class=\"hljs-keyword\">return</span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">a</span> <span class=\"hljs-attribute\">onClick</span>=<span class=\"hljs-value\">{this.showDialog}</span>&gt;</span>This is a button<span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">a</span>&gt;</span>\n    {this.state.showDialog ?\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">Portal</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">div</span>&gt;</span>\n          This is a popup!\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">div</span>&gt;</span>\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">Portal</span>&gt;</span>\n    : null}\n  )\n}</span></pre>"},{"slug":"validating-forms-react","title":"Validating Forms with React","subtitle":"How to use React JS and also validate forms","date":"2015-06-21T00:00:00.000Z","hidden":true,"html":"<h2 id=\"the-problem\">The Problem</h2>\n<p>Validating inputs on the web is very important, but it again, is very stateful, so how do we get forms to play nice with React?</p>\n<h2 id=\"thinking-about-what-is-needed\">Thinking about what is needed</h2>\n<p>Let&#39;s consider what such a form, which can validate its inputs might look like. What concerns must this component solve, what concerns can it delegate away?</p>\n<p>Definitely, the form should be created in a declarative way, like this:</p>\n<pre class=\"hljs\">&lt;ValidatedForm&gt;\n  &lt;ValidatedInput name=\"email\" validations=\"email\"/&gt; {/* Must be an email */}\n  &lt;ValidatedInput name=\"password\" validations=\"min:8\"/&gt; {/* Min 8 characters */}\n\n  {/* You should be able to put random stuff in the form and it should still render just fine */}\n\n  &lt;div&gt;\n    &lt;OrdinaryComponent/&gt;\n  &lt;/div&gt;\n\n  &lt;ValidatedSubmit/&gt;\n&lt;/ValidatedForm&gt;</pre><h2 id=\"setup\">Setup</h2>\n<p>Before we get into the business logic of it all, let&#39;s setup some basic components. The first one is called StandardInput. Skip this section if you&#39;re acquainted with how React works and you just want to know how I solve the validation problem.</p>\n<p>StandardInput</p>\n<pre class=\"hljs\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">StandardInput</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  static propTypes = {\n    error: PropTypes.string,\n    value: PropTypes.string,\n    onChange: PropTypes.func,\n    width: PropTypes.number,\n    className: PropTypes.string,\n    outerClassName: PropTypes.string\n  }\n  select = () =&gt; {\n    React.findDOMNode(<span class=\"hljs-keyword\">this</span>.refs.input).select();\n  }\n  render() {\n    <span class=\"hljs-keyword\">const</span> {error, width, outerClassName} = <span class=\"hljs-keyword\">this</span>.props;\n    <span class=\"hljs-keyword\">const</span> className = classNames(<span class=\"hljs-string\">\"edsx-input-40\"</span>, {\n      error: error\n    }, <span class=\"hljs-keyword\">this</span>.props.className);\n    <span class=\"hljs-keyword\">const</span> inputProps = _.omit(<span class=\"hljs-keyword\">this</span>.props, [<span class=\"hljs-string\">\"error\"</span>, <span class=\"hljs-string\">\"width\"</span>, <span class=\"hljs-string\">\"className\"</span>]);\n    <span class=\"hljs-keyword\">return</span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">div</span> <span class=\"hljs-attribute\">style</span>=<span class=\"hljs-value\">{{position:</span> \"<span class=\"hljs-attribute\">relative</span>\", <span class=\"hljs-attribute\">width</span>}} \n        <span class=\"hljs-attribute\">className</span>=<span class=\"hljs-value\">{outerClassName}</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">input</span> <span class=\"hljs-attribute\">ref</span>=<span class=\"hljs-value\">\"input\"</span> \n          <span class=\"hljs-attribute\">className</span>=<span class=\"hljs-value\">{className}</span> \n          {<span class=\"hljs-attribute\">...inputProps</span>}/&gt;</span>\n        {error ? \n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">InlineError</span> <span class=\"hljs-attribute\">error</span>=<span class=\"hljs-value\">{error}</span>/&gt;</span> \n        : null}\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">div</span>&gt;</span>\n    )</span>\n  }\n}</pre><p>InlineError</p>\n<pre class=\"hljs\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">InlineError</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  static propTypes = {\n    error: PropTypes.string\n  }\n  render() {\n    <span class=\"hljs-keyword\">const</span> errorStyle = {\n      position: <span class=\"hljs-string\">'absolute'</span>,\n      top: <span class=\"hljs-number\">3</span>,\n      right: <span class=\"hljs-number\">3</span>,\n      backgroundColor: <span class=\"hljs-string\">'#ea4843'</span>,\n      padding: <span class=\"hljs-number\">7</span>,\n      borderRadius: <span class=\"hljs-number\">3</span>,\n      color: <span class=\"hljs-string\">'white'</span>,\n      fontSize: <span class=\"hljs-number\">12</span>\n    }\n\n    <span class=\"hljs-keyword\">return</span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">div</span> <span class=\"hljs-attribute\">style</span>=<span class=\"hljs-value\">{errorStyle}</span>&gt;</span>\n        {this.props.error}\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-title\">div</span>&gt;</span>\n    )</span>\n  }\n}</pre><p>I&#39;ll leave it as an exercise to the reader to figure out the nitty gritty of these components, but they make up the basic declarative building blocks of inputs and validation.</p>\n<pre class=\"hljs\"><span class=\"hljs-comment\">// ES7</span>\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">ValidatedForm</span> <span class=\"hljs-keyword\">extends</span> <span class=\"hljs-title\">React</span>.<span class=\"hljs-title\">Component</span> </span>{\n  onSubmit = () =&gt; {\n\n  }\n  render() {\n    <span class=\"hljs-comment\">// Let's worry about what it renders a little later</span>\n  }\n}</pre><p>I have a ValidatedForm component, which takes ValidatedInput components as part of its body</p>\n<h2 id=\"inspiration-credits\">Inspiration, Credits</h2>\n<p><a href=\"http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html\">http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html</a></p>\n"},{"slug":"webpack-static-render","title":"Rendering Static Websites with Webpack","subtitle":"Using webpack to render a website statically, and react-router to switch between pages dynamically","date":"2015-06-21T00:00:00.000Z","hidden":true,"html":"<h2 id=\"why-would-you-want-to-do-this-\">Why would you want to do this?</h2>\n<ul>\n<li>Bots</li>\n<li>Github pages</li>\n<li>Download speed</li>\n</ul>\n<h2 id=\"this-post-was-inspired-by-\">This post was inspired by...</h2>\n<p><a href=\"http://jxnblk.com/writing/posts/static-site-generation-with-react-and-webpack/\">http://jxnblk.com/writing/posts/static-site-generation-with-react-and-webpack/</a></p>\n"}]}</script><script src="/bundle.js" data-reactid=".7dp7kc1c74.1.2"></script></body></html>