Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
cookpad summer internship 2018 - JavaScript
Search
Kazuhito Hokamura
September 18, 2018
Technology
0
9.5k
cookpad summer internship 2018 - JavaScript
Kazuhito Hokamura
September 18, 2018
Tweet
Share
More Decks by Kazuhito Hokamura
See All by Kazuhito Hokamura
TypeScriptとGraphQLで実現する 型安全なAPI実装 / TSKaigi 2024
hokaccha
5
4.9k
Kotlin製のGraphQLサーバーをNode.jsでモジュラモノリス化している話
hokaccha
0
3.7k
GraphQLの負債と向き合うためにやっていること
hokaccha
2
1.5k
ユビーのアーキテクチャに対する取り組み
hokaccha
1
460
RailsエンジニアのためのNext.js入門
hokaccha
7
21k
Cookpad Summer Internship 2021 Web Frontend
hokaccha
0
7.3k
巨大なモノリシック Rails アプリケーションの マイクロサービス化戦略 / 2019 microservices in cookpad
hokaccha
3
4k
巨大なRailsアプリケーションを「普通」にするための取り組み
hokaccha
1
1k
Web Frontend Improvement in Cookpad
hokaccha
1
1.1k
Other Decks in Technology
See All in Technology
AWS Network Firewall Proxyを触ってみた
nagisa53
0
210
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.8k
変化するコーディングエージェントとの現実的な付き合い方 〜Cursor安定択説と、ツールに依存しない「資産」〜
empitsu
4
1.3k
What happened to RubyGems and what can we learn?
mikemcquaid
0
250
ファインディの横断SREがTakumi byGMOと取り組む、セキュリティと開発スピードの両立
rvirus0817
1
1.3k
レガシー共有バッチ基盤への挑戦 - SREドリブンなリアーキテクチャリングの取り組み
tatsukoni
0
210
Claude_CodeでSEOを最適化する_AI_Ops_Community_Vol.2__マーケティングx_AIはここまで進化した.pdf
riku_423
2
530
usermode linux without MMU - fosdem2026 kernel devroom
thehajime
0
230
IaaS/SaaS管理における SREの実践 - SRE Kaigi 2026
bbqallstars
4
1.8k
プロポーザルに込める段取り八分
shoheimitani
1
190
GSIが複数キー対応したことで、俺達はいったい何が嬉しいのか?
smt7174
3
150
15 years with Rails and DDD (AI Edition)
andrzejkrzywda
0
180
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
97
6.5k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.1k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
300
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
180
Designing Experiences People Love
moore
144
24k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
160
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
54
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
130
The SEO Collaboration Effect
kristinabergwall1
0
350
BBQ
matthewcrist
89
10k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.9k
Unsuck your backbone
ammeep
671
58k
Transcript
JavaScript クックパッド サマーインターンシップ 10 Day Tech for service engineers
Agenda 1. JavaScript 2. TypeScript 3. React
https://code.visualstudio.com/
JavaScript
JavaScript •ブラウザで動作するプログラミング言語 •HTMLを動的に変更してインタラクティブなWebサイト を構築するために使われる •最近はNode.jsやReactNativeなどブラウザ以外でも動 作する環境も多くある
https://developer.mozilla.org/ja/
Development/Debug
基本文法
// جຊతʹconstΛ͏ const str = 'x'; const arr = [1,
2, 3]; // ఆٛޙʹ࠶ೖ͕ඞཁͳ߹letΛ͏ let message; if (err) { message = 'error!'; } else { message = 'ok!'; } 変数宣言
const num1 = 100; const num2 = 3.141592; const str1
= 'xxx'; const str2 = "yyy"; const str3 = `foo${str}bar`; const x = null; const bool = true; const re = /foo.+$/i; リテラル
const arr = [1, 2, 3]; arr[0] //=> 1 //
for-ofͰΠςϨʔγϣϯ for (const v of arr) { console.log(v); // 1, 2, 3 } // ֤छϝιουͰΠςϨʔγϣϯ arr.forEach((v) => { console.log(v); }) //=> 1, 2, 3 arr.map((v) => { return v * 2; }); //=> [2, 4, 6] arr.filter((v) => { return v > 1; }); //=> [2, 3] 配列
const obj = { foo: 'bar', fn: () => {
console.log('hello!') } }; obj.foo; //=> 'bar' obj.fn(); //=> hello! obj.a = 'b'; // Shorthand property names const x = 1; const y = 2; const obj2 = { x, y }; // { x: x, y: y } オブジェクト
// function จ function square(x) { return x * x;
} // function ࣜ const square = function(x) { return x * x; }; // Arrow function ࣜ const square = (x) => { return x * x; }; // Ҿ͕1ͭͷͱ͖ () ΛলུՄೳɻ{ } Λলུͨ͠߹୯Ұͷ͕ࣜॻ͚ͯͦͷࣜͷ͕return͞ΕΔ const square = x => x * x; square(5); //=> 25 関数
class Greeter { constructor(name) { this.name = name; } greet()
{ return `Hello ${this.name}!`; } } const g = new Greeter('hokaccha'); g.greet(); //=> 'Hello hokaccha!'; Class
Modules // lib/Greeter.js export default class Greeter { constructor(name) {
this.name = name; } greet() { return `Hello ${name}!`; } } export function hello(name) { return `Hello ${name}!`; }
Modules // app.js // default import import Greeter from './lib/Greeter';
// named import import { hello } from './lib/Greeter'; // mixed import Greeter, { hello } from './lib/Greeter';
非同期処理
同期 // Ծʹwait͕ॲཧΛϒϩοΫͨ͠ͱ͢Δͱ͍ͬͯΔؒʹԿͰ͖ͳ͍ wait(1000); doSomething(); 非同期 // ͕ͪ࣌ؒܦաͨ͠Β࣮ߦ͞ΕΔؔΛొ wait(1000, ()
=> { doSomething(); }); // ܧଓͯ͠ॲཧΛଓ͚ΒΕΔ
非同期処理の実装 •callback •Promise •async/await
callback http.get('/a', response => { // ... });
callback http.get('/a', responseA => { http.get('/b', responseB => { http.get('/c',
responseC => { // ... }); }); });
callback http.get('/a', (err, responseA) => { if (err) { return
handleError(err); } http.get('/b', (err, responseB) => { if (err) { return handleError(err); } http.get('/c', (err, responseC) => { if (err) { return handleError(err); } // ... }); }); });
Promise function get(url) { return new Promise((resolve, reject) => {
http.get(url, (err, response) => { if (err) { reject(err); } else { resolve(response); } }); }); } get('/a').then(response => { // do something }).catch(err => { // error handling });
Promise get('/a') .then(responseA => { return get('/b'); }) .then(responseB =>
{ return get('/c'); }) .then(responseC => { // do something }) .catch(err => { // error handling });
async/await async function req() { const responseA = await get('/a');
const responseB = await get('/b'); const responseC = await get('/c'); return responseC; } async function f() { try { const res = await req(); // do something } catch (err) { // error handling } }
DOM
DOM •HTML文書をプログラムから扱うためのAPI仕様 •JavaScriptの言語仕様とは別に仕様が策定されている
<!DOCTYPE html> <html> <head> <script src="app.js" defer></script> </head> <body> <button
id="button">Click Me!</button> <div id="message"></div> </body> </html>
// HTMLʹॻ͔Ε͍ͯΔ button ཁૉΛऔಘ const button = document.getElementById('button'); // click͞Εͨͱ͖ͷϋϯυϥʔΛొ
button.addEventListener('click', async () => { // HTTP RequestͰAPIΛݺͼग़͢ const response = await fetch('/message'); const body = await response.json(); // #messageͷ༰Λॻ͖͑Δ document.getElementById('message').innerHTML = body.message; });
// HTMLʹॻ͔Ε͍ͯΔ button ཁૉΛऔಘ const button = document.getElementById('button'); // click͞Εͨͱ͖ͷϋϯυϥʔΛొ
button.addEventListener('click', async () => { // HTTP RequestͰAPIΛݺͼग़͢ const response = await fetch('/message'); const body = await response.json(); // #messageͷ༰Λॻ͖͑Δ document.getElementById('message').innerHTML = body.message; }); %0."1*
TypeScript
TypeScript •Microsoftによって開発されているプログラミング言語 •JavaScriptに静的型付けの機能を取り入れたAltJS •JavaScriptのスーパーセット
JavaScript function greeter(person) { return "Hello, " + person; }
const user = "hokaccha"; const message = greeter(user);
TypeScript function greeter(person: string): string { return "Hello, " +
person; } const user = "hokaccha"; const message = greeter(user);
TypeScript function greeter(person: string): string { return "Hello, " +
person; } const user = [1, 2, 3]; const message = greeter(user); //=> error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.
Basic Types let str: string; let num: number; let bool:
boolean; let arr: string[]; let fn: (a: string, b: string) => boolean; type StrOrArr = string | string[]; type StrOrNull = string | null;
Generics class Queue<T> { private data: T[] = []; enqueue(item:
T) { return this.data.push(item); } dequeue(): T { return this.data.shift(); } } const queue = new Queue<number>(); queue.enqueue(10); queue.enqueue('x'); // Error!
Generics interface User { name: string; } async function getUser():
Promise<User> { const response = await fetch('/user'); const body = await response.json(); return body; } async function f() { const user: User = await getUser(); }
Gradual Typing
Gradual Typing •静的片付けを部分的に導入することができる型システム •TypeScriptでは型検査をしないany型により実現される
// Ҿͷܕ͕anyʹͳΔͷͰͲΜͳܕͰ௨Δ function greeter(person) { return "Hello, " + person;
} const user = [1, 2, 3]; const message = greeter(user); //=> ok Gradual Typing
Structural Subtyping
•部分型かどうかを構造が同じかどうかで判定する •静的型におけるダックタイピング Structural Subtyping
interface Person { firstName: string; lastName: string; } class User
{ firstName: string; lastName: string; } const user1: Person = new User(); // ok const user2: Person = { firstName: "Kazuhito", lastName: "Hokamura" }; // ok Structural Subtyping
class User { name: string; } class Product { name:
string; } const user: User = new Product(); // ok const product: Product = new User(); // ok Structural Subtyping
React
JavaScript Frameworks •jQuery •Backbone.js •Angular •Vue.js •React
None
class App extends React.Component { constructor(props) { super(props); this.state =
{ name: '' }; } handleInput(event) { this.setState({ name: event.target.value }); } render() { return <div> <input type="text" onInput={event => this.handleInput(event)} /> <div>Hello, {this.state.name}</div> </div>; } } ReactDOM.render(<App />, document.getElementById('app'));
class Button extends React.Component { render() { return <button onClick={()
=> this.props.onClick()}> <i className={`icon-${this.props.icon}`} /> {this.props.label} </button> } } <Button label="Click Me" icon="caret" onClick={() => alert('Hi!')} /> JSX
None
Lists and Keys class App extends React.Component { render() {
// users: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] const items = this.props.users.map(user => { return <li key={user.id}>{user.name}</li>; }); return <div>{items}</div>; } }
interface State { name: string; } interface Props { defaultName:
string; } class App extends React.Component<Props, State> { constructor(props: Props) { super(props); this.state = { name: props.defaultName }; } handleClick() { this.setState({ a: 'b' }); // Error } } <App foo="bar" />; // Error With TypeScript
設計パターン
stateとprops •state: コンポーネント自身が管理している状態 •props: 親コンポーネントから受け取る不変なパラメータ
Presentational Component •データを元にどういうviewを構築するかだけに専念する •状態を持たないStatelessなコンポーネントとして作る •親コンポーネントからもらうpropsのみに依存する
class Greeter extends React.Component<{}, {}> { render() { return <div
className="greeter">Hello, {this.props.name}</div>; } } // ୯ͳΔؔͱͯ͠ఆٛͰ͖Δ function Greeter(props) { return <div className="greeter">Hello, {this.props.name}</div>; } Stateless Component
Container Component •ツリーのルートでstateを持つコンポーネント •子のコンポーネントに状態を渡してツリーを構築する •イベントをハンドリングしてstateの更新をおこなう
class App extends React.Component { constructor(props) { super(props); this.state =
{ name: '' }; } handleInput(event) { this.setState({ name: event.target.value }); } render() { return <div> <input type="text" onInput={event => this.handleInput(event)} /> <Greeter name={this.state.name} /> </div>; } } Container Component
Container Component Stateless Component
1. イベント発生
1. イベント発生 2. 更新通知
1. イベント発生 2. 更新通知 3. state更新
1. イベント発生 2. 更新通知 3. state更新 4. DOM更新
Lifecycle
Component Lifecycle
Fetch data class App extends React.Component { constructor(props) { super(props);
this.state = { name: '' }; } async componentDidMount() { const response = await fetch('/user'); const body = await response.json(); this.setState({ name: body.name }); } render() { // ... } }
Practice
1. Rubyのサーバーから書籍のリストを取得して表示 2. タイトルでインクリメンタルサーチする機能を実装 3. 各フィールドでソートできる機能を実装 4. スタイルをいい感じにする
環境構築 $ npm install -g create-react-app $ create-react-app booklist-front \
--scripts-version=@hokaccha/create-react-app-ts-dev $ cd booklist-front $ yarn start