Last active
October 26, 2021 00:21
-
-
Save kenfdev/fe61c4fb03eec1ca6ff4 to your computer and use it in GitHub Desktop.
React
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// カスタム属性をそのままJSXで書くとコンパイル時に消えてしまう | |
React.render( | |
<h1 custom-attribute='foo'>いち・にぃ</h1>, | |
document.getElementById('example') | |
); | |
// 出力 | |
// <div id="example"> | |
// <h1 data-reactid=".0">いち・にぃ</h1> | |
// </div> | |
// カスタム属性には必ずdataをprefixとして記述する必要がある | |
React.render( | |
<h1 data-custom-attribute='foo'>いち・にぃ</h1>, | |
document.getElementById('example') | |
); | |
// 出力 | |
// <div id="example"> | |
// <h1 data-custom-attribute="foo" data-reactid=".0">いち・にぃ</h1> | |
// </div> | |
// Web Accessibility属性であるariaで始まる属性は正常に出力されます | |
React.render( | |
<div aria-hidden={true} />, | |
document.getElementById('example') | |
); | |
// 出力 | |
// <div id="example"> | |
// <div aria-hidden="true" data-reactid=".0"></div> | |
// </div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Stock = React.createClass({ | |
render: function() { | |
// 無駄にスタイルを適用してみる | |
var pStyle = { | |
color: 'red' | |
}; | |
// StockListコンポーネントのstockNodesをthis.props.childrenでアクセス | |
var tags = React.Children.map(this.props.children, function(child) { | |
return <p style={pStyle}>{child}</p> | |
}); | |
return ( | |
<div> | |
<h1> | |
{this.props.title} | |
</h1> | |
<h2> | |
{this.props.author} | |
</h2> | |
{tags} | |
</div> | |
); | |
} | |
}); | |
var StockList = React.createClass({ | |
render: function() { | |
var stockNodes = this.props.data.map(function (stock) { | |
console.log('stock',stock); | |
return ( | |
<Stock author={stock.user.id} title={stock.title}> | |
{stock.tags.map(function(tag){ return tag.name})} | |
</Stock> | |
); | |
}); | |
return ( | |
<div className="stockList"> | |
{stockNodes} | |
</div> | |
); | |
} | |
}); | |
var StockBox = React.createClass({ | |
loadStocksFromServer: function() { | |
// ajaxでAPIを叩く | |
$.ajax({ | |
// とりあえずちょっと取得してみたいだけなので3ストック限定で取得 | |
url: 'https://qiita.com/api/v2/users/' + this.props.userName + '/stocks?page=1&per_page=3', | |
dataType: 'json', | |
success: function(data) { | |
// 取得に成功したらstateに反映 | |
this.setState({data: data}); | |
}.bind(this), | |
error: function(xhr, status, err) { | |
console.error(this.props.username, status, err.toString()); | |
}.bind(this) | |
}); | |
}, | |
getInitialState: function() { | |
return {data: []}; | |
}, | |
componentDidMount: function() { | |
// コンポーネントがマウントされたら読み込み開始 | |
this.loadStocksFromServer(); | |
}, | |
render: function() { | |
return ( | |
<div className="stockBox"> | |
<h1>Stocks</h1> | |
<StockList data={this.state.data} /> | |
</div> | |
); | |
} | |
}); | |
// StockBoxコンポーネントのuserNameを適当に変えることで | |
// 誰かしらのストックをとってくる | |
React.render( | |
<StockBox userName="kenfdev" />, | |
document.getElementById('content') | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this creates 'load', 'load.completed' and 'load.failed' | |
var Actions = Reflux.createActions({ | |
load: { children: ['completed', 'failed'] }, | |
}); | |
// called before the 'load' action emits an event | |
Actions.load.preEmit = function () { | |
console.log(arguments); | |
}; | |
// called after preEmit | |
Actions.load.shouldEmit = function (isFail) { | |
console.log('isFail:' + isFail); | |
return !isFail; | |
}; | |
// when 'load' is triggered, call async operation and trigger related actions | |
Actions.load.listen(function (isFail) { | |
// By default, the listener is bound to the action | |
// so we can access child actions using 'this' | |
dummyPromiseCall(isFail).then(this.completed).catch(this.failed); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// a dummy promise call which resolves or rejects 1000ms later | |
var dummyPromiseCall = function (isFail) { | |
var deferred = Q.defer(); | |
// fake asynchronous call | |
setTimeout(function () { | |
if (isFail) { | |
deferred.reject('Failed!'); | |
} else { | |
deferred.resolve('Success!'); | |
} | |
}, 1000); | |
return deferred.promise; | |
}; | |
/*********Actions*********/ | |
// this creates 'load', 'load.completed' and 'load.failed' | |
var Actions = Reflux.createActions({ | |
load: { children: ['completed', 'failed'] }, | |
}); | |
// called before the 'load' action emits an event | |
Actions.load.preEmit = function () { | |
console.log(arguments); | |
}; | |
// called after preEmit | |
Actions.load.shouldEmit = function (isFail) { | |
console.log('isFail:' + isFail); | |
return !isFail; | |
}; | |
// when 'load' is triggered, call async operation and trigger related actions | |
Actions.load.listen(function (isFail) { | |
// By default, the listener is bound to the action | |
// so we can access child actions using 'this' | |
dummyPromiseCall(isFail).then(this.completed).catch(this.failed); | |
}); | |
// `promise` style | |
// Actions.load.listen(function(isFail) { | |
// Actions.load.promise(dummyPromiseCall(isFail)); | |
// }); | |
// `listenAndPromise` style | |
// Actions.load.listenAndPromise(dummyPromiseCall); | |
/*********Actions*********/ | |
/*********Store*********/ | |
// Creating Data Stores(https://github.com/reflux/refluxjs#creating-data-stores) | |
var Store = Reflux.createStore({ | |
// Listening to many Actions at once(https://github.com/reflux/refluxjs#listening-to-many-actions-at-once) | |
listenables: [Actions], | |
// called when 'load' triggers | |
onLoad: function () { | |
this.trigger('Loading...'); | |
}, | |
// Listenabled and asynchronous actions(https://github.com/reflux/refluxjs#listenables-and-asynchronous-actions) | |
// called when 'load.completed' triggers | |
onLoadCompleted: function (msg) { | |
this.trigger(msg); | |
}, | |
// called when 'load.failed' triggers | |
onLoadFailed: function (msg) { | |
this.trigger(msg); | |
}, | |
}); | |
/*********Store*********/ | |
/*********React Component*********/ | |
var Hello = React.createClass({ | |
// Convenience mixin for React(https://github.com/reflux/refluxjs#convenience-mixin-for-react) | |
// https://github.com/reflux/refluxjs#using-refluxlistento | |
mixins: [ | |
Reflux.listenTo(Store, 'onLoad'), | |
Reflux.listenTo(Store, 'onLoadComplete'), | |
Reflux.listenTo(Store, 'onLoadFailed'), | |
], | |
// initialize this.state.message | |
getInitialState: function () { | |
return { | |
message: 'initial message', | |
}; | |
}, | |
handleLoadSuccess: function () { | |
// trigger the 'load' Action | |
Actions.load(false /*isFail*/); | |
}, | |
handleLoadFail: function () { | |
// trigger the 'load' Action | |
Actions.load(true /*isFail*/); | |
}, | |
// called when the Store fires 'onLoad' | |
onLoad: function (msg) { | |
this.setState({ message: msg }); | |
}, | |
// called when the Store fires 'onLoadComplete' | |
onLoadComplete: function (msg) { | |
this.setState({ message: msg }); | |
}, | |
// called when the Store fires 'onLoadFailed' | |
onLoadFailed: function (msg) { | |
this.setState({ message: msg }); | |
}, | |
render: function () { | |
return ( | |
<div> | |
<button onClick={this.handleLoadSuccess}>Load Success</button> | |
<button onClick={this.handleLoadFail}>Load Fail</button> | |
<div>{this.state.message}</div> | |
</div> | |
); | |
}, | |
}); | |
React.render(<Hello />, document.body); | |
/*********React Component*********/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ExampleApplication = React.createClass({ | |
render: function () { | |
// ここでthis.props.nameを無理矢理変更 | |
// 出力結果は「mutated name!」になります | |
return <p>{(this.props.name = 'mutated name!')}</p>; | |
}, | |
}); | |
var start = new Date().getTime(); | |
React.render( | |
<ExampleApplication name="kenfdev" />, | |
document.getElementById('container') | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var MyComponent = React.createClass({ | |
// static method | |
statics: { | |
message: 'Hello', | |
staticMethod: function () { | |
// < v0.13rc:thisはコンポーネント(MyComponent)に自動バインド | |
// v0.13rc:thisはコンポーネントに自動バインドされない | |
return this.message; | |
}, | |
}, | |
render: function () {}, | |
}); | |
// messageを持つオブジェクトを準備 | |
var caller = { | |
message: 'Hey!', | |
}; | |
// Greetings component | |
var Greetings = React.createClass({ | |
render: function () { | |
// < v0.13rc:staticMethodはMyCompoentにバインドされているので出力結果は「Hello」 | |
// v0.13rc:staticMethodはMyComponentにバインドされておらず、呼び出し元をcallerに明示的に設定している為出力結果は「Hey!」 | |
return <div>{MyComponent.staticMethod.call(caller)}</div>; | |
}, | |
}); | |
React.render(<Greetings></Greetings>, document.body); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Helloコンポーネントを2秒後にアンマウントさせる為の設定 | |
var timeoutBeforeUnmount = 2000; | |
// The Hello Component | |
var Hello = React.createClass({ | |
getInitialState: function () { | |
return { message: 'World' }; | |
}, | |
componentDidMount: function () { | |
var self = this; | |
setTimeout( | |
function () { | |
// setStateを呼び出す | |
self.setState({ message: 'again to the World' }); | |
}, | |
// Helloコンポーネントの1秒後にsetStateを発火させる | |
timeoutBeforeUnmount + 1000 | |
); | |
}, | |
render: function () { | |
return <div>Hello {this.state.message}</div>; | |
}, | |
}); | |
React.render(<Hello />, document.getElementById('container')); | |
// Helloコンポーネントを2秒後にアンマウント | |
setTimeout(function () { | |
React.unmountComponentAtNode(document.getElementById('container')); | |
}, timeoutBeforeUnmount); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# react.js < v0.13rc 例外発生 | |
Uncaught Error: Invariant Violation: replaceState(...): Can only update a mounted or mounting component. | |
# v0.13rc <= react.js 警告止まり | |
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Hello = React.createClass({ | |
getInitialState: function () { | |
return { count: 0 }; | |
}, | |
handleClick: function (e) { | |
// countをインクリメント | |
this.setState({ count: this.state.count + 1 }); | |
// 同一関数内で再度インクリメント | |
// 2になってくれるかと思いきや、this.state.countは即時反映されるわけではないので、上のsetStateも下のsetStateも「0 + 1」を実行してしまい、結果は「1」になってしまう。 | |
this.setState({ count: this.state.count + 1 }); | |
}, | |
render: function () { | |
return ( | |
<div onClick={this.handleClick}> | |
Click Me and the Count will try to increment by 2 but will fail! | |
<br /> | |
Count: {this.state.count} | |
</div> | |
); | |
}, | |
}); | |
React.render(<Hello />, document.body); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
this.setState({ count: this.state.count + 1 }); | |
// 'this._pendingState'なら即時反映された値にアクセスできる | |
this.setState({ count: this._pendingState.count + 1 }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Hello = React.createClass({ | |
getInitialState: function () { | |
return { count: 0 }; | |
}, | |
handleClick: function (e) { | |
// setStateに関数を渡すことが可能。この計算は「0 + 1」となる | |
this.setState(function (state, props) { | |
return { count: state.count + 1 }; | |
}); | |
// 最新状態のstateにアクセス可能なので、この計算は「1 + 1」となる | |
this.setState(function (state, props) { | |
return { count: state.count + 1 }; | |
}); | |
}, | |
render: function () { | |
return <div onClick={this.handleClick}>Count: {this.state.count}</div>; | |
}, | |
}); | |
React.render(<Hello />, document.body); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment