20211016のReactに関する記事は11件です。

React Native for mac 2021年10月版

備忘録です。 準備 色んなバージョンでやってみたのですが2021年10月現在、ちゃんと動いたのは0.63.4でした。 まずは0.63.4で空のプロジェクトを作ります。 zsh対応はしてる? 最近はbashじゃなくzshが標準になってしまったので、react native環境を作る時、.zshenvにPATHの設定をしておきましょうね。 export PATH=$PATH:$HOME/.nodebrew/current/bin プロジェクト作成 npx react-native init HogeProj --template react-native@0.63.4 パッケージのインストール cd HogeProj npx react-native-macos-init プロジェクト名の修正 app.jsonに記載されているプロジェクト名と、package.jsonに記載されているプロジェクト名が大文字小文字違いでこの状態でビルド・実行するとエラーになります。公式にもよく読むと書いてあります。ProjectName has not been registeredって。 app.json { "name": "hogeproj", "displayName": "HogeProj" } package.json { "name": "hogeproj", "version": "0.0.1", "private": true, "scripts": { package.jsonの"name"とapp.jsonの"name"を一致させておきます。 なんならプロジェクト名を最初から小文字のみにしておくのもいいかと。 実行 npx react-native run-macos
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + Express + Docker の環境構築

Reactで作成した画面からExpressで作成したAPIを呼び、取得したデータを画面表示するところまでを構築していきます。 React/Expressはそれぞれ別のDockerコンテナで動作させます。 ディレクトリ app/  ├── docker/  │ ├── docker-compose.yml  │ └── Dockerfile  ├── backend/  └── frontend/ docker/ の2ファイルはホスト側で作成しますが、その他の backend/ と frontend/ 内のファイルは全てコンテナ側で作成していきます。 Docker Dockerfile と docker-compose.yml を作成し、コンテナを起動します。 ファイル作成 React、Express で共通で使う Dockerfile を1つ作成します。 Dockerfile FROM node:14 今回はひとまずnodeが動けば良いので何も設定していません。 次に docker-compose.yml を作成します。 docker-compose.yml version: '3' networks: react_express: driver: bridge services: frontend: # React用のコンテナ build: . container_name: front tty: true volumes: - ../frontend:/frontend working_dir: "/frontend" ports: - 3001:3000 networks: - react_express backend: # Express用のコンテナ build: . container_name: back tty: true volumes: - ../backend:/backend working_dir: "/backend" ports: - 3002:3000 networks: - react_express network : 2つのコンテナを同じネットワーク内に配置します。 volumes : 開発の便宜上、ホストとコンテナでファイル共有しています。 ports : frontend、backendの各サーバ用のポート 3000 を、それぞれホストのポート 3001、3002 に転送しています。 コンテナの起動 コンテナを起動します。 $ cd docker/ $ docker-compose up -d ... $ docker-compose ps back docker-entrypoint.sh node Up 0.0.0.0:3002->3000/tcp,:::3002->3000/tcp front docker-entrypoint.sh node Up 0.0.0.0:3001->3000/tcp,:::3001->3000/tcp UpとなっていればOKです。 Express (Backend) プロジェクト作成 docker exec を使って、Express用のコンテナ (back) に入ります。 $ docker exec -u node -it back /bin/bash package.json を作成します。 $ npm init -y Expressをインストールします。 $ npm install express APIの作成 index.js を作成します。 index.js const express = require('express'); const app = express(); const port = 3000; app.get('/user', (req, res) => { res.json([{ id: 1, name: "Taro" }, { id: 2, name: "Jiro" }]); }); app.listen(port, () => console.log(`Server running on port ${port}`)); /user にリクエストが来たときに、jsonデータを返すようにしています。 Expressサーバの起動 準備ができたので、Expressサーバを起動します。 $ node index.js Server running on port 3000 React (Frontend) プロジェクト作成 別のターミナルを立ち上げ、docker exec を使って、React用のコンテナ (front) に入ります。 $ docker exec -u node -it front /bin/bash create-react-app コマンドを使って、プロジェクトを作成します。 (ドットを付けることで、ディレクトリ直下に作成できます) $ npx create-react-app . Proxyの設定 Dockerのネットワーク環境における Front/Backend の各オリジン ( http://xxx:yy )は、 Frontend : http://frontend:3000 Backend : http://backend:3000 のように異なるため、CORS (Cross-Origin Resource Sharing) の設定をする必要があります。 ここでは、Front側に Proxy を使う方法で回避します。以下2パターンのどちらかを使います。 方法1: package.json に proxy を設定する package.json に以下を追記します。 pacage.json "proxy": "http://backend:3000", この設定があると、text/html 以外のヘッダのリクエストを proxy のアドレスを origin としてリクエストするようになるため、Same-Origin として認識されます。 方法2: http-proxy-middleware を使う 複数の proxy を設定したい場合にはこちらの方法を使います。 src/setupProxy.js を作成します。 src/setupProxy.js const proxy = require('http-proxy-middleware') module.exports = function(app) { app.use(proxy('/user', { target: 'http://backend:3000' })) } この設定により、Reactアプリに対して /user にリクエストが来たときに http://backend:3000 にリクエストが飛ぶことになり、方法1と同様に Same-Origin として通信できます。 app.use(proxy()) は複数記述できるため、リクエストのパスにより別の proxy に分けて設定することもできます。 ちなみに create-react-app は、npm start の実行時に setupProxy.js を自動で読み込んで処理をするようになっているため、他のファイルにimportをする必要はありません。(ただし、npm run buildでは機能しません。) 画面の作成 src/App.js を以下に編集します。 src/App.js import { useEffect, useState } from 'react'; const App = () => { const [users, setUsers] = useState([]); useEffect(() => { fetch('/user') .then(res => res.json()) .then(data => { setUsers(data); }).catch(err => { console.log(err) }); }, []); return ( <div> {users.map((user, index) => <p key={index}>{ user.name }</p> )} </div> ); } export default App; 画面読み込み時に fetch('/user') が実行され、Proxyの設定によりExpressサーバ ( http://backend:3000/user ) にリクエストが送られます。 このAPIから取得したデータを users ステートに格納し、画面に表示します。 Reactサーバの起動 Reactサーバを起動します。 $ yarn start ホスト側のブラウザで http://localhost:3001/ にアクセスすると、 Taro Jiro が画面に表示されることが確認できました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScriptでReact.js + Redux Hooks + Express + SQLite3で作るチュートリアルアプリ

こんにちは、Morishing362と申します。 日本的な巨大メーカー企業でUI/UXエンジニアをしております。 普段はTypeScript/Flutter/Rust/C++などを触っています。 仕事以外でツールを作る機会があり、Reactでやってみたく、まずはチュートリアルとしてアプリを作ってみたので晒します。 各フレームワークの役割 React: フロントエンドフレームワーク Redux: Reactの状態管理 Express: HTTPサーバーフレームワーク SQLite3: データベース 目標のアプリ 左側に比較的簡単な状態管理のカウンター機能、右側にデータベースを使った非同期処理を伴うユーザー追加機能を持つ、 なんの意味もないアプリです。 環境 OS: Ubuntu 20.04 (Docker Container) Yarn: 1.22.5 SQLite3クライアント: 3.31.1 npmやYarnのインストール手順は世の中にたくさんあるので省きます。 忙しい人向け 色々と忙しいと思いますのでソースコード置いておきます。 サーバーサイド: https://github.com/Morishing362/ExpressTutorial フロントエンド: https://github.com/Morishing362/ReduxTutorial サーバーサイド ディレクトリ作成 サーバーサイドから行きます! まずは作業ディレクトリ作成とその初期化から $ mkdir ExpressTutorial $ cd ExpressTutorial $ yarn init TypeScriptをインストール yarn add @types/node typescript ts-node express, sqlite3, corsをインストール $ yarn add express @types/express cors @types/cors sqlite3 @types/sqlite3 yarn devでサーバー起動するようにpackage.jsonにscriptsを以下のように追加(お好みで) package.json { ...dependenciesとか... ... "scripts": { "dev": "ts-node ./src/index.ts" } } サーバーサイド接続テスト Expressを使ってテストします src/index.tsに以下のように書きます src/index.ts import express from 'express'; const app = express(); app.get('/', (req, res) => { res.send('Connection Success'); }); app.listen(4001, () => { console.log('The server is listening on port 4001'); }); そしてコンソールでyarn devと入力して、サーバーが立ち上がるはずです。 $ yarn dev yarn run v1.22.5 $ ts-node ./src/index.ts The server is listening on port 4001 あとはcurlなりブラウザなりで、http://localhost:4001/ にアクセスしてみてください Connection Success!が出れば成功です 目標の構成 それでは本格的にExpressとSQLite3データベースを使ってユーザー読み込み、登録、削除機能を作っていきましょう 今回はテスト駆動開発ではなく、テストコードの書き方などは省きます 構成は以下の通り src |-- db | `-- database.sqlite3 |-- controllers.ts // データベース読み書き |-- index.ts // データベース接続とサーバー起動 `-- router.ts // URLによるルーティング規則 データベース用意 まずはコンソールに戻り、SQLite3クライアント(インストールしておいてください)を使ってデータベースを作成します ここではid、名前、年齢だけの超単純なテーブルを作ります ExpressTutorialディレクトリで、 以下のように入力してデータベースを作成し、sqlite3コンソールに入ります。 $ sqlite3 src/db/database.sqlite3 sqlite3 > そして以下のSQLコマンドでテーブルを作ります sqlite3 > create table User(id integer primary key, name text, age integer); sqlite3 > .table User .tableと打ち込んでUserがでればテーブルができています。 データベースの用意ができましたのでExpressサーバーを書いていきましょう 実装 controllers.tsから書きます controllersではデータベースとの情報のやりとりを行います 読み込み(readAllUsers)、追加(insertSingleUser)、削除(deleteSingleUser)を書きます sqlite3ライブラリは非同期処理をするので、async functionとして定義します コード末尾export defaultでこれらの関数を外に出します src/controllers.ts import express from 'express'; import { db } from './index'; async function root(req: express.Request, res: express.Response) { res.status(200).send('Connection Success'); } async function readAllUsers(req: express.Request, res: express.Response) { db.all( "select * from User", (err, rows) => { if (err) { sendError(res, err); } else { res.status(200).json(rows); } }, ); } async function insertSingleUser(req: express.Request, res: express.Response) { const data = req.body const stmt = db.prepare("insert into User(name, age) values(?, ?)"); stmt.run([data.name, data.age], function (this, err) { if (err) { sendError(res, err); } else { res.status(200).json({ id: this.lastID, name: data.name, age: data.age, }); } }); } async function deleteSingleUser(req: express.Request, res: express.Response) { db.run("delete from User where id = ?", [req.params.id], (err) => { if (err) { sendError(res, err); } else { res.status(200).send(); } }); } function sendError(res: express.Response, err: Error) { res.status(401).json({ status: "error", message: err.message }); } export default { root, readAllUsers, insertSingleUser, deleteSingleUser, }; 次にrouter.tsを書きます router.tsではURLによるルーティングを実現します controllers.tsの関数たちと、URLを紐づける役割を果たします。 httpメソッド名の第一引数にroot(http://localhost:4001 )からのルートを代入し、第二引数に先程のcontrollers.tsで定義した関数を代入します 最後にexport defaultで外に出します src/router.ts import express from 'express'; import controller from './controllers'; const router = express.Router(); router.get('/', controller.root); router.get('/user/all', controller.readAllUsers); router.post('/user/insert', controller.insertSingleUser); router.delete('/user/delete/id/:id', controller.deleteSingleUser); export default router; index.tsはサーバーサイドのエントリーポイントであり、データベースの接続とExpressサーバーの起動を処理します src/index.ts import express from 'express'; import path from 'path'; import sqlite3 from 'sqlite3'; import router from './router'; import cors from 'cors'; const app = express(); const dirname = path.resolve(); export const db = new sqlite3.Database( path.join(dirname, 'src', 'db', 'database.sqlite3'), (err) => { if (err) { console.log(err.message); } }); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cors()); app.use(router); app.listen(4001, () => { console.log('The server is listening on port 4001'); }); ここまでできたらyarn devで起動し、 各URLにHTTPリクエストを送ってみて、データベースを読み込み/書き換えできるかテストしてみましょう ちなみに筆者はよくHTTPリクエストのテストに、こちらのVSコードで試せるHTTPクライアントのプラグインを使います https://marketplace.visualstudio.com/items?itemName=Aaron00101010.http-client サーバーサイドは完了です 今日は力尽きたのでまた明日フロントエンドの詳細を書きます アドバイス、コードレビューなど気がついたことがございましたらコメントよろしくお願いいたします
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScriptでReact + Redux(Hooks) + Express + SQLite3を使ったチュートリアルアプリ

こんにちは、Morishing362と申します。 日本的な巨大メーカー企業の新卒2年目で、UI/UXエンジニアをしております。 普段はTypeScript/Flutter/Rust/C++などを触っています。 仕事以外でツールを作る機会があり、Reactでやってみたく、まずはチュートリアルとしてアプリを作ってみたので晒します。 各フレームワークの役割 React: フロントエンドフレームワーク Redux: Reactの状態管理 Express: HTTPサーバーフレームワーク SQLite3: データベース 目標のアプリ 左側に比較的簡単な状態管理のカウンター機能、右側にデータベースを使った非同期処理を伴うユーザー追加機能を持つ、なんの意味もないアプリです。 環境 OS: Ubuntu 20.04 (Docker Container) Yarn: 1.22.5 SQLite3クライアント: 3.31.1 npmやYarnのインストール手順は世の中にたくさんあるので省きます。 忙しい人向け 色々と忙しいと思いますのでソースコード置いておきます。 サーバーサイド: https://github.com/Morishing362/ExpressTutorial フロントエンド: https://github.com/Morishing362/ReduxTutorial サーバーサイド ディレクトリ作成 サーバーサイドから行きます!まずは作業ディレクトリ作成とその初期化から $ mkdir ExpressTutorial $ cd ExpressTutorial $ yarn init TypeScriptをインストール yarn add @types/node typescript ts-node express, sqlite3, corsをインストール $ yarn add express @types/express cors @types/cors sqlite3 @types/sqlite3 yarn devでサーバー起動するようにpackage.jsonにscriptsを以下のように追加(お好みで) package.json { ...dependenciesとか... ... "scripts": { "dev": "ts-node ./src/index.ts" } } サーバーサイド接続テスト Expressを使ってテストします src/index.tsに以下のように書きます src/index.ts import express from 'express'; const app = express(); app.get('/', (req, res) => { res.send('Connection Success'); }); app.listen(4001, () => { console.log('The server is listening on port 4001'); }); そしてコンソールでyarn devと入力して、サーバーが立ち上がるはずです。 $ yarn dev yarn run v1.22.5 $ ts-node ./src/index.ts The server is listening on port 4001 あとはcurlなりブラウザなりで、http://localhost:4001/ にアクセスしてみてください Connection Success!が出れば成功です。 目標の構成 それでは本格的にExpressとSQLite3データベースを使ってユーザー読み込み、登録、削除機能を作っていきましょう。 今回はテスト駆動開発ではなく、テストコードの書き方などは省きます。 構成は以下の通り src |-- db | `-- database.sqlite3 |-- controllers.ts // データベース読み書き |-- index.ts // データベース接続とサーバー起動 `-- router.ts // URLによるルーティング規則 データベース用意 まずはコンソールに戻り、SQLite3クライアント(インストールしておいてください)を使ってデータベースを作成します。ここではid、名前、年齢だけの超単純なテーブルを作ります。ExpressTutorialディレクトリで、以下のように入力してデータベースを作成し、sqlite3コンソールに入ります。 $ sqlite3 src/db/database.sqlite3 sqlite3 > そして以下のSQLコマンドでテーブルを作ります sqlite3 > create table User(id integer primary key, name text, age integer); sqlite3 > .table User .tableと打ち込んでUserがでればテーブルができています。データベースの用意ができましたのでExpressサーバーを書いていきましょう。 実装 controllers.tsから書きます。controllersではデータベースとの情報のやりとりを行います。読み込み(readAllUsers)、追加(insertSingleUser)、削除(deleteSingleUser)を書きます。sqlite3ライブラリは非同期処理をするので、async functionとして定義します。コード末尾export defaultでこれらの関数を外に出します。 src/controllers.ts import express from 'express'; import { db } from './index'; async function root(req: express.Request, res: express.Response) { res.status(200).send('Connection Success'); } async function readAllUsers(req: express.Request, res: express.Response) { db.all( "select * from User", (err, rows) => { if (err) { sendError(res, err); } else { res.status(200).json(rows); } }, ); } async function insertSingleUser(req: express.Request, res: express.Response) { const data = req.body const stmt = db.prepare("insert into User(name, age) values(?, ?)"); stmt.run([data.name, data.age], function (this, err) { if (err) { sendError(res, err); } else { res.status(200).json({ id: this.lastID, name: data.name, age: data.age, }); } }); } async function deleteSingleUser(req: express.Request, res: express.Response) { db.run("delete from User where id = ?", [req.params.id], (err) => { if (err) { sendError(res, err); } else { res.status(200).send(); } }); } function sendError(res: express.Response, err: Error) { res.status(401).json({ status: "error", message: err.message }); } export default { root, readAllUsers, insertSingleUser, deleteSingleUser, }; 次にrouter.tsを書きます router.tsではURLによるルーティングを実現します。controllers.tsの関数たちと、URLを紐づける役割を果たします。httpメソッド名の第一引数にroot(http://localhost:4001 )からのルートを代入し、第二引数に先程のcontrollers.tsで定義した関数を代入します。最後にexport defaultで外に出します。 src/router.ts import express from 'express'; import controller from './controllers'; const router = express.Router(); router.get('/', controller.root); router.get('/user/all', controller.readAllUsers); router.post('/user/insert', controller.insertSingleUser); router.delete('/user/delete/id/:id', controller.deleteSingleUser); export default router; index.tsはサーバーサイドのエントリーポイントであり、データベースの接続とExpressサーバーの起動を処理します src/index.ts import express from 'express'; import path from 'path'; import sqlite3 from 'sqlite3'; import router from './router'; import cors from 'cors'; const app = express(); const dirname = path.resolve(); export const db = new sqlite3.Database( path.join(dirname, 'src', 'db', 'database.sqlite3'), (err) => { if (err) { console.log(err.message); } }); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cors()); app.use(router); app.listen(4001, () => { console.log('The server is listening on port 4001'); }); ここまでできたらyarn devで起動し、 各URLにHTTPリクエストを送ってみて、データベースを読み込み/書き換えできるかテストしてみましょう。ちなみに筆者はよくHTTPリクエストのテストに、こちらのVSコードで試せるHTTPクライアントのプラグインを使います https://marketplace.visualstudio.com/items?itemName=Aaron00101010.http-client サーバーサイドは完了です 今日は力尽きたのでまた明日フロントエンドの詳細を書きます。アドバイス、コードレビューなど気がついたことがございましたらコメントよろしくお願いいたします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】Qiita デイリー LGTM 数ランキング【自動更新】

他のタグ AWS Android Docker Git Go iOS Java JavaScript Linux Node.js PHP Python Rails React Ruby Swift TypeScript Vim Vue.js 初心者 集計について 期間: 2021-10-17 ~ 2021-10-18 GitHub スターをもらえるととっても励みになります LGTM 数ランキング 1 位: React から利用する API のロギングでロケーション情報を格納する Python api SPA logging React 6 LGTM 3 ストック @yaitaimo さん ( 2021-10-17 19:58 に投稿 ) 2 位: 【React】グローバルなState管理をする React.createContext Context.Provider 初心者 入門 React 1 LGTM 2 ストック @YSasago さん ( 2021-10-17 13:17 に投稿 ) 3 位: React Native + Expoで(iOS,Android)開発環境を構築する Android iOS React reactnative expo 1 LGTM 0 ストック @ozv-y-amano さん ( 2021-10-19 01:29 に投稿 ) 4 位: Reactの特徴その2 イベント React コンポーネント State props 1 LGTM 0 ストック @jizya さん ( 2021-10-17 12:50 に投稿 )
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[React] React+TypeScript 実践

React初心者がReact+TypeScriptについて勉強した時のメモです。 型がないせいでバグっている例 ボタンを押したらJSONPlaceholderのTodoのデータをaxiosを使ってデータ取得するプログラム。 https://jsonplaceholder.typicode.com/todos App.tsx import axios from "axios"; import { useState } from "react"; import { Todo } from "./Todo"; export default function App() { const [todos, setTodos] = useState<any>([]); const onClickFetchData = () => { axios.get("https://jsonplaceholder.typicode.com/todos").then((res) => { setTodos(res.data); console.log(res); }); }; return ( <div className="App"> <button onClick={onClickFetchData}>データ取得</button> {todos.map((todo) => ( <Todo title={todo.title} userid={todo.userid} /> ))} </div> ); } Todo.tsx export const Todo = (props) => { const { title, userid } = props; return <p>{`${title}(ユーザー:${userid})`}</p>; }; データ取得したらユーザー名がundefinedになるというバグが発生している。 取得データに型を定義する App.tsx import axios from "axios"; import { useState } from "react"; import { Todo } from "./Todo"; type TodoType = { userId: number; id: number; title: string; completed: boolean; }; export default function App() { const [todos, setTodos] = useState<Array<TodoType>>([]); const onClickFetchData = () => { axios .get<Array<TodoType>>("https://jsonplaceholder.typicode.com/todos") .then((res) => { setTodos(res.data); }); }; return ( <div className="App"> <button onClick={onClickFetchData}>データ取得</button> {todos.map((todo) => ( <Todo key={todo.id} title={todo.title} userid={todo.userId} /> ))} </div> ); } 取得するデータにtypeとして型を定義する。 axiosのget部分とuseStateの部分に取得データの型を当てることエディターの補完も効くようになりどこが間違っているかが分かる。 今回の場合は、以下の部分のuseridのiが小文字になっていたからというのが分かった。 <Todo title={todo.title} userid={todo.userid} /> propsに型定義 type TodoType = { userId: number; title: string; }; export const Todo = (props: TodoType) => { const { title, userId } = props; return <p>{`${title}(ユーザー:${userId})`}</p>; }; propsも同様に型を定義しておくことでiの小文字に気づけバグを防げる。 PickとOmit 型定義の部分(今回でいうTodoType)を切り出した場合に型を呼び出す際にPickかOmitを使うことで効率的に管理できる。 切り出したTodoType types/todo.ts export type TodoType = { userId: number; id: number; title: string; completed: boolean; }; Pick(抽出) import { TodoType } from "./types/todo" export const Todo = (props: Pick<TodoType, "userId" | "title">) => { const { title, userId } = props; return <p>{`${title}(ユーザー:${userId})`}</p>; }; Pickを使うことでこのコンポーネントで必要な型の情報のみ抜き出せる。 Omit(省略) import { TodoType } from "./types/todo" export const Todo = (props: Omit<TodoType, "id" | "completed">) => { const { title, userId } = props; return <p>{`${title}(ユーザー:${userId})`}</p>; }; OmitはPickの逆でTodoTypeの中から必要ないものを除いた形。 コンポーネント自体の型 export const Todo: FC<Pick<TodoType, "userId" | "title">> = (props) => { const { title, userId } = props; return <p>{`${title}(ユーザー:${userId})`}</p>; }; 関数コンポーネント自体の型定義。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからReact始めたい人のための今日だけでできるTODO#24 TODOアプリの作成② リストの表示

TODOリストの表示 前回作成したdata.jsonをaxiosを利用して取得して表示します。 コードは以下のとおりです。 App.js import React, { useState, useEffect } from 'react'; import axios from 'axios'; const todoDataUrl = 'http://localhost:3100/todos'; function App() { const [todoList, setTodoList] = useState([]); useEffect(() => { const fetchData = async () => { const response = await axios.get(todoDataUrl); setTodoList(response.data); }; fetchData(); }, []); return ( <> <h1>TODO List</h1> <ul> {todoList.map((todo) => ( <li key={todo.id}> {todo.content}({todo.done ? '完了' : '未完了'}) </li> ))} </ul> </> ); } import useState とuseEffectが利用できるようにimportします。 さらにaxiosが利用できるようにaxiosもimportしておきます。 App.js import React, { useState, useEffect } from 'react'; import axios from 'axios'; axiosで通信する先を定義 json-serverを利用して、ローカルにサーバーを作りました。 コマンドを打ったポート先のURLとdata.jsonに定義したデータ配列の名前を組み合わせたローカルホストURLを定義します。 App.js const todoDataUrl = 'http://localhost:3100/todos'; App()の中に処理を記述 大きく分けて3つ記述を追加します。 - useState()による状態と状態を更新するための関数の定義 - useEffct()でマウント後に実行する処理 - return()の中に取得したデータを表示する処理 表示は以下のようになります。 filter()を使って未完了と完了を分けて表示する filter関数を使って未完了のリストと完了のリストを分けて表示されるようにします。 App.js const inCompletedList = todoList.filter((todo) => { return !todo.done; }); const completedList = todoList.filter((todo) => { return todo.done; }); それぞれ変数を定義してtodoListからfilter()を使って新しい配列を作成します。 あとはreturn()の中に記述map()を使って展開します。 App.js <h2>未完了TODO</h2> <ul> {inCompletedList.map((todo) => ( <li key={todo.id}> {todo.content}({todo.done ? '完了' : '未完了'}) </li> ))} </ul> <h2>完了TODO</h2> <ul> {completedList.map((todo) => ( <li key={todo.id}> {todo.content}({todo.done ? '完了' : '未完了'}) </li> ))} </ul>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[React] TypeScript基礎

React初心者です。 React+TypeScriptについて勉強した時のTypeScriptについてのメモです。 TypeScriptとは? Microsoftが開発したオープンソースの言語。 JavaScriptに型という概念を組み込むことで安全にバグの少ない開発ができるように。 開発者間で認識を合わせやすい。 エディタで補完が効くので開発効率UP。 コンポーネント志向のReactと相性がいい。 TypeScript基本の型 boolean型 let bool: boolean = true; number型 数値 let num: number = 0; string型 文字 let str: string = "AA"; Array型 配列 let arr1: Array<number> = [0, 1, 2]; let arr2: number[] = [0, 1, 2]; any型 どんな方でもエラーにならない let any1: any = false; void型 関数の型でvoidは何も返却していないことを表す 何も返却していない場合は、TypeScriptが察してくれるのであえて書かなくても平気。 const funcA = (): void => { const test = "TEST"; } null型 nullを表す。 let null1: null = null; undefined型 何も設定されていない状態を表す let undefined1: undefined = undefined; object 型 オブジェクト内の型を指定 let obj: { id: number, name: string } = {id: 0, name: "AAA" }; 実装の例1 (引数に型指定) export const Test = () => { const calcTotal = (num: number) => { const total = num * 5; console.log(total); }; const onClickTest = () => { calcTotal(10); }; return ( <> <button onClick={onClickTest}>実行</button> </> ); }; 計算した合計をコンソールで出力する。 この場合引数に型を指定しないとcalcTotal(10);の部分の数値に"1,000"のような形の文字列を入れた時NaNとコンソールに出力されてしまうので型を指定することで安全。 ちなみにcalcTotal("10");のような数値の文字列を入れた場合はJavaScriptが変換してくれるので計算結果が普通に出力される。 実装の例2 (返却値の型指定) export const Test = () => { const calcTotal = (num: number): number => { const total = num * 5; return total }; const onClickTest = () => { console.log(calcTotal(10)); }; return ( <> <button onClick={onClickTest}>実行</button> </> ); }; 今度は計算結果を返却する場合、返却値の型を指定することでtotalの値が数値であることを保証。 実装例3 (変数の型指定) export const Test = () => { const calcTotal = (num: number): number => { const total = num * 5; return total }; const onClickTest = () => { let total: number = 0; total = calcTotal(10) console.log(total); }; return ( <> <button onClick={onClickTest}>実行</button> </> ); }; 変数の型を指定することで変数は数値であることを保証。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからWeb開発を始める人に知ってほしいGithubプロジェクト

はじめに この記事ではProgrammingを始める方や学生でこれからエンジニアを目指されている方々に私がよく紹介しているGithubのプロジェクトを紹介しています。どのプロジェクトも英語ですが、どのプロジェクトもきっと皆さんのキャリアにとって役に立つはずです。ぜひお役立ていただければと思います。 1. Web Developer Roadmap このプロジェクトではWeb Developerになるまでにどのような知識が必要なのかを体型的にまとめてくれています。 これはFrontendのRoadmapの例ですが、以下のようにTopicにつき質問がいくつかあるのでそれに答えられるようになっていけば必然とFrontend開発を学ぶことができます。 HPもあり、こちらの方だとより詳しく言語ごとのロードマップなども紹介されています。 2. AI Expert Roadmap こちらはWeb開発ではないけど似たようなプロジェクトがあったので参考までに。 AIを学びたい方向けのロードマップ。 3. First Contributions エンジニアだろうとデータサイエンティストだろうとGithubを使った共同開発はもはや避けては通れません。 First ContributionsではどのようにしてPull Requestを作りコミュニティやチームに貢献しするのかを実際に体験することができます。GitHubでPull Requestを作ったことがない人は1度こちらで練習しておきましょう。 ちなみにこちらのプロジェクトは日本語に翻訳されています。 4. RealWorld RealWorldはMedium.comのクローンアプリをデモアプリとして提供しています。 100を超える言語やフレームワークごとにそれぞれ実装されており、自分が学びたい言語、フレームワークの実務レベルの使い方をデモアプリを再現することで学ぶことができます。 難易度は少し高いですが、お勧めです。私は今でも新しいフレームワークについて学ぶ機会があると一度こちらでフレームワーク独特の書き方や作法などを確認したりしています。 5. Web Development for Beginner Microsoftが提供しているウェブ開発のために学習教材。Microsoftが提供しているだけあって教材の質はかなり高い印象です。HTML,CSS, JSがメインのコースです。 6. Awesome Programmingの世界では分野ごとの便利なライブラリや情報を集めたAwesomeというレポジトリがGithub上に存在します。基本的にどの分野でもAwesomeが作られており、自分がこれから勉強する言語、フレームワークの情報を集めたりするのにお勧めです。 7. Coding Interview University こちらはコーディングインタビューのための情報をまとめたもの。 就職が近い方は目を通しておくといいでしょう。 終わりに どのプロジェクトも有益ですので自分に合ったものをぜひ使ってみてください。 これらのプロジェクトは知っているだけで違うとおもいますので、これから学習を始める方の一助になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[React] グローバルなstate管理(useContext)

React初心者がグローバルなstate管理について勉強した時のメモです。 現状 以下のような階層構造の時に、 App → ComponentA → ComponentB → ComponentC ComponentCにあさひというUser名の値を渡したい場合、各Componentでpropsのバケツリレーをしないといけない。 App.jsx import { ComponentA } from "./components/ComponentA"; export const App = () => { const name = "あさひ"; return ( <> <ComponentA name={name} /> </> ); }; ComponentA import { ComponentB } from "./ComponentB"; export const ComponentA = (props) => { const { name } = props; return ( <> <p>ComponentA</p> <ComponentB name={name} /> </> ); }; ComponentB.jsx import { ComponentC } from "./ComponentC"; export const ComponentB = (props) => { const { name } = props; return ( <> <p>ComponentB</p> <ComponentC name={name} /> </> ); }; ComponentC.jsx export const ComponentC = (props) => { const { name } = props; return ( <> <p>ComponentC</p> <p>{name}</p> </> ); }; Contextを使ったstate管理 Providerの作成 Providerを作成します。 UserProvider.jsx import React, { createContext } from "react"; export const UserContext = createContext({}) export const UserProvider = (props) => { const { children } = props; const contextName = "あさひ" return ( <UserContext.Provider value={{ contextName }}> {children} </UserContext.Provider> ) } ここで今回受け渡したい値のUser名あさひを設定します。 createContextを使用し以下のように囲うことで{children}に入ってくるコンポーネントではどこでもvalueの値を参照することができます。 <UserContext.Provider value={{ contextName }}> {children} </UserContext.Provider> App.jsx import { ComponentA } from "./components/ComponentA"; import { UserProvider } from "./provider/UserProvider"; export const App = () => { return ( <UserProvider> <ComponentA/> </UserProvider> ); }; 作ったProviderコンポーネントをApp.jsxでComponentAを囲います。 これでComponentA以下の全てのComponentでProviderで設定した値の参照ができます。 useContext useContextを使用してComponentCで値を取得します。 今回はUserContextのcontextNameを取得しています。 ComponentC.jsx import { useContext } from "react"; import { UserContext } from "../provider/UserProvider"; export const ComponentC = () => { const name = useContext(UserContext); return ( <> <p>ComponentC</p> <p>{name.contextName}</p> </> ); }; useStateと使う場合 useStateと一緒に使うことでstateを渡すことができます。 ProviderでuseStateを定義し、valueに値を設定します。 今回はカウントアップのためのstateをComponentCに渡していきます。 UserProvider.jsx import React, { createContext, useState } from "react"; export const UserContext = createContext({}); export const UserProvider = (props) => { const { children } = props; const [count, setCount] = useState(0); return ( <UserContext.Provider value={{ count, setCount }}> {children} </UserContext.Provider> ); }; ComponentC import { useContext } from "react"; import { UserContext } from "../provider/UserProvider"; export const ComponentC = () => { const { count, setCount } = useContext(UserContext); return ( <> <p>ComponentC</p> <p>{count}</p> <button onClick={() => setCount(count + 1)}>ボタン</button> </> ); }; useContextでProviderでセットしたstateを受け取ることで使用できます。 めっちゃ便利!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScriptでuseRefを使う

import { useRef } from "react"; const sendInput = (inputValue: string | undefined) => { console.log(inputValue) } function App() { const inputRef = useRef<HTMLInputElement>(null); return ( <div className="App"> <input ref={inputRef} type="text" /> <button onClick={()=>sendInput(inputRef.current?.value)}>送信</button> </div> ); } export default App;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む