React.jsの薄い場所

Reactは、もちろん、複雑なインターフェイスの作成を簡素化する画期的なテクノロジーですが、抽象化と同様に、独自の小さな問題と機能があります。 私の練習では、あまり明白ではない4つに出会いました。 それをバグと呼ぶのは難しいです-それは単にライブラリの機能です。 今日はそれらについてお話します。


最初の瞬間-0.14でアルゴリズムが変更され、ルート要素を再描画するかどうかを決定しました


このような微妙な点がありますが、ドキュメントには記載されていません。 バージョン0.14より前では、 React.render()呼び出しは常に、渡されたものを再描画しました。 ルート要素へのリンクを保存できます...

 const element = <MyComponent />; 

...そしてReact.render(element)呼び出すたびにアプリケーションが再描画されます。

0.14では、 props改善され、アルゴリズムは「よりスマート」になりました。 現在、同じオブジェクトが到着すると、 propsstateすでに描画されてstateことを確認します。 つまり、要素へのリンクを保存したら、そのstate変更するか、コピーを作成するか、レンダリングの前にsetProps()実行する必要があります。

 import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { render() { const date = Date.now(); return <div>The time is {date}</div>; } } const app = document.getElementById("app"); const element = <MyComponent />; const ref = ReactDOM.render(element, app); ReactDOM.render(element, app); //    render() ref.forceUpdate(); //   

別の方法は、常に新しい要素を作成することです:

 const app = document.getElementById("app"); const ref = ReactDOM.render(<MyComponent />, app); ReactDOM.render(<MyComponent />, app); 


2番目の瞬間-コントロールを使用している場合、ReactDOM.render()の呼び出しは、コントロールのイベントと同期して実行する必要があります


, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
を使用, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
 ,  . .,             ReactDOM.render() . 

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
 ,  . .,             ReactDOM.render() . 

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
 ,  . .,             ReactDOM.render() . 

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !

, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !

, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
 ,  . .,             ReactDOM.render() . 

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
 ,  . .,             ReactDOM.render() . 

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !
, . ., ReactDOM.render() .

, , , - - .

import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { bizLogic1(e.currentTarget.value); bizLogic2(e.currentTarget.value); bizLogic3(e.currentTarget.value); } render() { return ( <select size="3" value={this.props.selectedId} onChange={this.handleChange.bind(this)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> ); } }

... FLUX- , , , selectedId , - bizLogic1-3 , . , bizLogic* , , , .

let selectedId = 1; const app = document.getElementById("app"); function bizLogic1(newValue) { selectedId = newValue; renderAfterwards(); } function bizLogic2(newValue) { //... renderAfterwards(); } function bizLogic3(newValue) { //... renderAfterwards(); } let renderRequested = false; function renderAfterwards() { if (!renderRequested) { // , , // render() <select> window.setTimeout(() => { ReactDOM.render(<MyComponent selectedId={selectedId} />, app, () => { renderRequested = false; }); }, 0); } } //initial render ReactDOM.render(<MyComponent selectedId={selectedId} />, app);
, , select' — , 'onchange' , bizLogic1-3 , props . , . React ( ) <select'> . ReactDOM.render() , , , , .

, UI ReactDOM.render() .

Dispatcher FLUX:

class MyComponent extends React.Component { handleChange(e) { dispatch({action: "ACTION_OPTION_SELECT", value: e.currentTarget.value}); } ... } function dispatch(action) { if (action.action === "ACTION_OPTION_SELECT") { bizLogic1(action); bizLogic2(action); bizLogic3(action); } ReactDOM.render(<MyComponent selectedId={selectedId} />, app); }

TestUtils.Simulate.change

, , React TestUtils , , . , ReactUtils , . , target currentTarget :

describe("MyInput", function() { it("refuses to accept DEF", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); var fakeInput = {value: "DEF"}; TestUtils.Simulate.change(rootNode, {currentTarget: fakeInput}); // , TestUtils currentTarget expect($(rootNode).val()).toEqual("abc"); // , .. handleChange <input> currentTarget }); });
( , ) ,

2 — React , . - , , .

:

import {$} from "commonjs-zepto"; import React from "react"; import ReactDOM from "react-dom"; class MyComponent extends React.Component { handleChange(e) { let value = e.currentTarget.value; if (!value.match(/[0-9]/)) bizLogic(value); } render() { return <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} />; } } const app = document.getElementById("app"); describe("MyInput", function() { it("refuses to accept digits", function() { var ref = ReactDOM.render(<MyComponent value="abc" />, app); var rootNode = ReactDOM.findDOMNode(ref); $(rootNode).val("abc1"); // TestUtils.Simulate.change(rootNode); //handleChange <input value="abc1"> // React "abc" expect($(rootNode).val()).toEqual("abc"); // , , .. value React' // , bizLogic , , "abc" }); });
, , !

Source: https://habr.com/ru/post/J273995/


All Articles