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.4k
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.4k
Kotlin製のGraphQLサーバーをNode.jsでモジュラモノリス化している話
hokaccha
0
3.5k
GraphQLの負債と向き合うためにやっていること
hokaccha
2
1.4k
ユビーのアーキテクチャに対する取り組み
hokaccha
1
400
RailsエンジニアのためのNext.js入門
hokaccha
7
20k
Cookpad Summer Internship 2021 Web Frontend
hokaccha
0
7.2k
巨大なモノリシック Rails アプリケーションの マイクロサービス化戦略 / 2019 microservices in cookpad
hokaccha
3
3.8k
巨大なRailsアプリケーションを「普通」にするための取り組み
hokaccha
1
960
Web Frontend Improvement in Cookpad
hokaccha
1
1.1k
Other Decks in Technology
See All in Technology
ドキュメント管理の理想と現実
kazuhe
3
310
品質文化を支える小さいクロスファンクショナルなチーム / Cross-functional teams fostering quality culture
toma_sm
0
180
Pythonデータ分析実践試験 出題傾向や学習のポイントとテクニカルハイライト
terapyon
1
110
AIにおけるソフトウェアテスト_ver1.00
fumisuke
1
330
意思決定を支える検索体験を目指してやってきたこと
hinatades
PRO
0
390
OPENLOGI Company Profile
hr01
0
63k
AIによるコードレビューで開発体験を向上させよう!
moongift
PRO
0
350
今日からはじめるプラットフォームエンジニアリング
jacopen
8
1.9k
もう難しくない!誰でもカンタンDocker入門 〜30分であなたのPCにアプリを立ち上げる〜
devops_vtj
0
180
Cross Data Platforms Meetup LT 20250422
tarotaro0129
1
920
Linuxのパッケージ管理とアップデート基礎知識
go_nishimoto
1
700
AIでめっちゃ便利になったけど、結局みんなで学ぶよねっていう話
kakehashi
PRO
1
520
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
23
2.7k
VelocityConf: Rendering Performance Case Studies
addyosmani
329
24k
4 Signs Your Business is Dying
shpigford
183
22k
Building a Modern Day E-commerce SEO Strategy
aleyda
40
7.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Designing Experiences People Love
moore
142
24k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
34
2.2k
Unsuck your backbone
ammeep
671
57k
How GitHub (no longer) Works
holman
314
140k
GraphQLとの向き合い方2022年版
quramy
46
14k
Documentation Writing (for coders)
carmenintech
70
4.7k
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