Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Angular使いがReactでアプリ組んだらこうなった
Search
puku0x
June 05, 2019
Technology
1.9k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Angular使いがReactでアプリ組んだらこうなった
React勉強会@福岡 vol.2
puku0x
June 05, 2019
More Decks by puku0x
See All by puku0x
え?フロントエンドエンジニアの ワイがインフラも!?
puku0x
1
1.5k
新メンバーのために、シニアエンジニアが環境を作る時代
puku0x
0
1.6k
Agent Skills 入門
puku0x
0
2.2k
ファインディにおけるフロントエンド技術選定の歴史
puku0x
2
2.3k
生成AIではじめるテスト駆動開発
puku0x
0
1.5k
実践!カスタムインストラクション&スラッシュコマンド
puku0x
2
3.4k
Nx × AI によるモノレポ活用 〜コードジェネレーター編〜
puku0x
0
1.7k
ファインディにおけるフロントエンド技術選定の歴史
puku0x
2
330
ファインディでのGitHub Actions活用事例
puku0x
9
4k
Other Decks in Technology
See All in Technology
SREは、MCPとAutopilotをこう使え!
kazumax55
2
840
AI時代の「技術的負債」の変質ー概念の終焉と再解釈、エージェントと共に向かう先
nwiizo
0
2.7k
あるけみー式LTスライド作成術
alchemy1115
2
220
Genieを崇めよ
kameitomohiro
0
150
「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜 / iOSDC Japan 2026
nakamuuu
0
160
20260912_スクフェス三河
kgnkhkr
0
380
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
26
14k
幾何アルゴリズムで なめらかなピン操作を / iOSDC Japan 2026 / smoothpin
kazumanagano
0
350
すぐできる衛星通信対応 あとは山奥に行くだけ
tatetate55
0
130
目の前の楽しいが人生を変える - コミュニティの螺旋の歩き方と楽しむコツ / change your life
soudai
PRO
5
630
2026_devsumi_ozono.pdf
o3
3
510
AI に書かせたその API、 “信頼” できますか?
nagix
0
110
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
300
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
540
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
Mind Mapping
helmedeiros
1
360
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Faster Mobile Websites
deanohume
310
32k
Side Projects
sachag
456
43k
Claude Code のすすめ
schroneko
67
230k
Code Review Best Practice
trishagee
74
20k
Transcript
Angular使いが Reactでアプリ組んだらこうなった React勉強会@福岡 vol.2
Noriyuki Shinpuku ng-fukuoka organizer VEGA corporation Co., Ltd. @puku0x
Angular
Supported by Google
Full-fledged & opinionated Angular Protractor Forms PWA Augury Language Services
Router Elements CDK Universal Karma Labs Compiler i18n Http Material Animations CLI
React
Supported by Facebook
React is a library
Scalable apps with React?
1. Use TypeScript $ npm i -D @types/{react,react-dom}
2. Abstraction • Keep components SIMPLE • Better testability Component
Service HttpClient Axios
HttpClient (inspired by Angular’s HttpClient) export abstract class HttpClient {
abstract get<T>(url: string, options?: HttpRequestOptions) abstract post<T>(url: string, data?: unknown, options?: HttpRequestOptions) abstract put<T>(url: string, data?: unknown, options?: HttpRequestOptions) abstract delete(url: string, options?: HttpRequestOptions) }
Services const fetchUser = async (id: number) => { const
res = await httpClient.get<User>(`/users/${id}`); return res.data; }; export const UserService = { fetch: fetchUser, ... };
3. Separation of concerns • Business logic • State management
• Components
State management • react-redux + redux-thunk + re-ducks pattern •
Keep reducers PURE • Good practices from NgRx ◦ Good Action Hygiene ◦ Entity pattern
Good Action Hygiene export enum UserActionTypes { // ACTION_NAME =
'[Source] Event', FETCH_REQUEST = '[User/Page] Fetch Request', FETCH_SUCCESS = '[User/API] Fetch Success', FETCH_FAILURE = '[User/API] Fetch Failure', ... } Good Action Hygiene with NgRx Mike Ryan https://www.youtube.com/watch?v=JmnsEvoy-gY
Thunk Actions export interface FetchUserRequest extends Action<UserActionTypes.FETCH_REQUEST> { payload: {
id: number }; } export function fetchUserRequest(id: number): ThunkAction<Promise<Success | Failure>, State, undefined, Actions> { return async dispatch => { dispatch<FetchUserRequest>({ type: UserActionTypes.FETCH_REQUEST, payload: { id } }); const result = await UserService.fetch(id) .then(response => fetchUserSuccess(response)) .catch(error => fetchUserFailure(error)); return dispatch(result); }; }
Entity pattern interface Dictionary<T> { [id: number]: T; } export
interface EntityState<T> { ids: number[]; entities: Dictionary<T>; }
EntityAdapter (inspired by NgRx’s EntityAdapter) export const adapter: EntityAdapter<User> =
createEntityAdapter<User>(); export function reducer(state = initialState, action: Action): State { switch (action.type) { ... case UserActionTypes.UPDATE_SUCCESS: { const { user } = action.payload; return adapter.update(user, { ...state, isFetching: false }); } ... } } Immutable operation with less boilerplates
Selectors const usersStateSelector = (state: { users: UserState }) =>
state.users; const { selectAll, selectEntities } = adapter.getSelectors(); export const usersSelector = createSelector( usersStateSelector, selectAll );
3. Separation of concerns (for components) • Business logic •
State management • Components ◦ Page components ◦ Container components ◦ Presentational components
Structure of components Page component Router params Store Container components
Presentational components http://localhost:3000/users/:id
Page components type Props = RouteComponentProps<{ id: string }>; const
UserDetailPage: FunctionComponent<Props> = props => { const { match, location } = props; const { id } = match.params; const params = new URLSearchParams(location.search); const edit = params.get('edit') || false; return <UserDetail id={+id} edit={+edit} />; }; export default withRouter(UserDetailPage);
Container components type Props = { id: number; }; export
const UserDetail: FunctionComponent<Props> = props => { const { id } = props; const user = useSelector(userSelector); const dispatch = useDispatch(); useEffect(() => dispatch(fetchUserRequest(id)), [id]); return <UserDetailComponent user={user} />; };
Presentational components type Props = RouteComponentProps & { user: User;
}; const UserDetailComponent: FunctionComponent<Props> = props => { const { user, history } = props; const goBack = useCallback(() => history.goBack(), []); return <>...</> }; export const UserDetail = withRouter(UserDetailComponent);
4. Lazy loading • Suspense + lazy() • Route-based lazy
loading import { lazy } from 'react'; export const UsersPage = lazy(() => import('./UsersPage'));
Routing separation <Suspense fallback={<div>Loading...</div>}> <Switch> <Route exact path="/" render={() =>
<Redirect to="/dashboard" />} /> <Route path="/dashboard" component={DashboardPage} /> <Route path="/groups" component={GroupsPage} /> <Route path="/users" component={UsersPage} /> </Switch> </Suspense> “Separation of concerns” for routing
Routing separation for child pages const UsersPage: FunctionComponent = ()
=> ( <Suspense fallback={<div>Loading...</div>}> <Switch> <Route exact path="/users" component={UserListPage} /> <Route exact path="/users/new" component={UserCreatePage} /> <Route exact path="/users/:id"component={UserDetailPage} /> <Route exact path="/users/:id/edit" component={UserEditPage} /> </Switch> </Suspense> ); export default UsersPage;
src/ models/ user.model.ts index.ts pages/ UsersPage/ UserDetailPage/ components/ containers/ UserDetailPage.tsx
index.ts UsersPage.tsx index.ts MainPage/ index.ts 5. Naming & structuring like way shared/ components/ Button/ Button.tsx Button.test.tsx Button.stories.tsx index.ts helpers/ hooks/ index.ts : App.tsx AuthenticatedRoute.tsx index.tsx index.html services/ user/ user.service.ts user.service.test.ts index.ts store/ user/ actions/ user.action.ts user.action.test.ts index.ts reducers/ selectors/ states/ index.ts https://angular.io/guide/styleguide
Other libraries?
Styling • emotion • classnames
Form validation • Formik (v1.5) ◦ v2.0.1-rc.x is not recommended
https://github.com/jaredpalmer/formik/pull/1570 • Yup
Routing • react-router (v5.0) • connected-react-router const middleware = process.env.NODE_ENV
!== 'production' ? [require('connected-react-router/immutable').routerMiddleware(history), thunk] : [require('connected-react-router').routerMiddleware(history), thunk]; const middlewares = applyMiddleware(...middleware);
State management • react-redux (v7.1) ◦ Requires adding custom @types/react-redux
• redux-thunk ◦ Requires overloading redux’s Dispatch<Action> https://github.com/reduxjs/redux-thunk/pull/247 • reselect
Testing • jest • enzyme • react-test-renderer • redux-mock-store
Follow good practices
One more option
We don’t use create-react-app Because it doesn’t allow us to
use path alias.
How was it?
Awesome!
• Type safe • Simple • Easy to refactor •
Performant • Scalable
Summary • The experience of helped us to make app
◦ Using TypeScript ◦ Abstraction ◦ Separation of concerns ◦ Lazy loading ◦ Naming
Always keep an open mind
Thank you! @puku0x Noriyuki Shinpuku