20211007のReactに関する記事は8件です。

React Study(1)

React勉強はじめます  これまでバックエンド側のゴリゴリのJavaとかOracle PL/SQLしかやってこなかったので、ユーザーサイドの画面側の技術についてめちゃくちゃ疎い。しかもここ5年くらいは本当に管理職の仕事しかしていないからすべての技術知識が化石級に…。  しかしながらこれからの時代、バックエンドからフロントエンド、何ならクラウド含めたインフラ環境まで知識としてつけておかないとエンジニアのマネジメントもままならない。  ってことで、フロントエンドの技術中心に勉強始めようと思います。  世のため人のためになる、っていうよりは、自分学習メモなのでさらっと書いていきます。 とりあえずHello React的なところから ありきたりなことやっていきます。 環境回り  まずはReact環境の作り方。って言ってもWindowsでnode.jsインストーラーで入れるだけです。 nodeバージョン c:\projects>node -v v14.18.0 c:\projects>npm -v 6.14.15 Hello React  create-react-appしてプロジェクト作ります。 プロジェクト作成 c:\projects>npx create-react-app react_practice (省略) Happy hacking!  出来上がったらnpm startするとブラウザが勝手に開きます。 起動・動作確認 c:\projects\react_practice>npm start http://localhost:3000/ がデフォルトのポートになっているのでそのアドレスが勝手に開きます。  初歩の初歩はまずここから。  これから画面の通り、src/App.jsをいじって勉強していきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】スタイルの扱い方 

はじめに Reactのスタイルの扱い方についてまとめてみました。私のプロジェクトではCSS Modulesを使うことが多いです。CSS Modulesは、今までのCSSの書き方と同じように書くことができます。 Inline Style Reactでも各タグにstyle属性を記述することで、スタイルの適用をすることができます。JavaScriptで記述するので、style={}のように波括弧で囲み、その中にオブジェクトでCSSに対応する要素を指定しているため、style={{}}と記載します。 App.jsx //文字を赤色に変更 export const App = () => { return ( <> <h1 style={{ color: "red" }}>こんにちは</h1> </> ); }; index.html import ReactDom from "react-dom"; import { App } from "./App"; ReactDom.render(<App />, document.getElementById("root")); 事前に定義する場合 App.jsx const contentStyle = { color: "blue", fontSize: "100px", }; return ( <> {console.log("a")} <h1 style={{ color: "red" }}>こんにちは</h1> <p style={contentStyle}>よろしくおねがいします。</p> </> ); }; index.html import ReactDom from "react-dom"; import { App } from "./App"; ReactDom.render(<App />, document.getElementById("root")); CSS Modulesを使う場合 はじめにパッケージをインストールします。私の環境がnode14なので、node14に対応したnode-sassを入れます。 terminal $ node -v v14.17.6 $ yarn add node-sass@4.14.1 .module.scssという拡張子で、CSSファイルを作成します。 CssModules.module.scss .title { margin: 0; color: red; } .button { background-color: #ddd; border: none; padding: 8px; border-radius: 8px; &:hover { background-color: #aaa; color: blue; cursor: pointer; } } 使うコンポーネントでimportします。 CssModules.module import classes from "./CssModules.module.scss"; export const CssModules = () => { return ( <> <p className={classes.title}>CSS Modulesです</p> <button className={classes.button}>ボタン</button> </> ); };
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsプロジェクト内でReactを使う方法

RailsとReactを分離させてSPAで動かす記事はたくさん見つかるけど、そうではなくRailsプロジェクトの一部でReactを使う方法。 react-railsというgemを使う方法です。ほぼ以下のgemでの導入方法に近い記事です。 reactjs/react-rails: Integrate React.js with Rails views and controllers, the asset pipeline, or webpacker. 環境 Rails 6.1.4 Ruby 3.0.0 Reactの導入 まず導入したいrailsプロジェクトディレクトリ内に移動し、railsコマンドでReactとその関連ファイルをインストール。 % rails webpacker:install:react インストールすると、app/javascript/packs/hello_react.jsxが作成される。これを任意のviewファイルに挿入する。 中身は以下。 // Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file, // like app/views/layouts/application.html.erb. All it does is render <div>Hello React</div> at the bottom // of the page. import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' const Hello = props => ( <div>Hello {props.name}!</div> ) Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string } document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hello name="React" />, document.body.appendChild(document.createElement('div')), ) }) ファイル先頭にも書いてある通り、<%= javascript_pack_tag 'hello_react' %>をrailsのviewファイルに挿入すればこのコンポーネントがレンダリングされる。 ReactコンポーネントをRailsのviewで表示する 実際にやってみる。 ※以下は挿入したいviewファイルが既にあればとくにやらなくて大丈夫です。 viewを作成するためBookモデルのscaffoldを実行しマイグレート。 % rails g scaffold Book title:string content:text % rails db:migrate rails sで先に画面を確認。 http://localhost:3000/books ここに先ほどのhello_react.jsxを挿入してみる。 app/views/books/index.html.erb <% # 以下に挿入 %> <%= javascript_pack_tag 'hello_react' %> <p id="notice"><%= notice %></p> <h1>Books</h1> <table> <thead> <tr> <th>Title</th> <th>Content</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @books.each do |book| %> <tr> <td><%= book.title %></td> <td><%= book.content %></td> <td><%= link_to 'Show', book %></td> <td><%= link_to 'Edit', edit_book_path(book) %></td> <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New Book', new_book_path %> 表示を確認すると、確かにHello React!がレンダリングされている。 ただこの状態だと挿入した行の位置に関わらずReactコンポーネントが最後にレンダリングされてしまうのでそれを解消する。 react-railsの導入 Gemfileに以下を追記。 gem 'react-rails' 追記したgemをインストール。 % bundle install 次に以下のコマンドを実行。 % rails g react:install するとapp/javascript/componentsというフォルダが作られるので、ここにhello_react.jsxをここに移動。 レンダリングに関しては react-railsがやってくれるので、移動した後以下のように変更。 app/javascript/components/hello_react.jsx // Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file, // like app/views/layouts/application.html.erb. All it does is render <div>Hello React</div> at the bottom // of the page. import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' const Hello = props => ( <div>Hello {props.name}!</div> ) Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string } // 以下を削除 // document.addEventListener('DOMContentLoaded', () => { // ReactDOM.render( // <Hello name="React" />, // document.body.appendChild(document.createElement('div')), // ) // }) // 以下を追記 export default Hello react-railsを導入したことによって、react_componentというメソッドが使えるようになる。レンダリングしたいReactコンポーネントの読み込みも以下のように記述を変更。 # 以下を削除 <%= javascript_pack_tag 'hello_react' %> # 以下を追記 <%= react_component('hello_react') %> <p id="notice"><%= notice %></p> <h1>Books</h1> <table> <thead> <tr> <th>Title</th> <th>Content</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @books.each do |book| %> <tr> <td><%= book.title %></td> <td><%= book.content %></td> <td><%= link_to 'Show', book %></td> <td><%= link_to 'Edit', edit_book_path(book) %></td> <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New Book', new_book_path %> これで再度レンダリングしてみる。 これで任意の場所にReactコンポーネントを差し込むことができた! viewファイルから値を渡したい場合は、以下のようにする。 <%= react_component('hello_react', { name: "react-rails" }) %> これ以降追加したいReactコンポーネントがあれば、app/javascript/components配下にjsxなりtsxのファイルを作ればいい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React:Bootstrap Tabタイトルを子コンポーネントから変更

ReactでBootstrapのTabsを使っていて、keyのあるオブジェクトから作ったTabのタイトルを子コンポーネントからkeyを指定して変更した。メモを2点ほど。 ComponentParent export default function ComponentParent(props) { const [tabTitles, setTabTitles] = useState(null) const [currentKey, setCurrentKey] = useState(null) useEffect(() => { // ここでは、例なので単純にオブジェクト直接記述 setTabTitles({ 111: "タブ1", 222: "タブ2", 333: "タブ3" }) setCurrentKey(111) }, []) useEffect(() => { // 何か選択が変わった時の処理 },[currentKey]} const TabSample = () => { if (!currentKey || !tabTitles) return <div>Loading...</div>; return ( <Tabs id="tab-sample" activeKey={ currentKey } onSelect={(k) => setCurrentKey(k)} >                 {/* メモ1: オブジェクトをmapで展開するにはこう書けばよいみたい。 */} { Object.keys(tabTitles).map(key => <Tab eventKey={ key } title={ tabTitles[key]} key={ key }></Tab> } </Tabs> ) } const changeTabTitle = (key, title) => { /* メモ2: tabTitles[key] = title してセットする方法だと更新されない。展開すること。 */ setTabTitles({...tabTitles, [key]: title}) } return ( <TabSample /> <ComponentChild changeTabTitle={ (key, title) => changeTabTitle(key, title) }  /> ) } ComponentChild export default function ComponentChild(props) { const clickChangeTabTitle1 = () => { props.changeTabTitle(111, "タブA") } return ( <button onClick={ clickChangeTabTitle1 } >タブ1のタイトル変更</button> ) }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Electron+ReactでHello world

ElectronのUIをReactで作ってみます。 次のステップで作っていきます。 Reactアプリをcreate-react-appで作る。 作ったReactアプリをElectronで読み込み表示する。 ググるとlocalhost:3000で起動したReactアプリを読み込む例が多いですが、ここではビルドしたものを読み込むことにします。 ※環境: Windows 10 Home, Node.js v14.17.4, Electron v15.1.1 Reactアプリを作る まずはcreate-react-appでReactアプリを作ります。 アプリ名は適当にerhelloとしますが何でもOKです。 > npx create-react-app erhello 一応Hello worldですのでApp.jsでHello, world!と表示するように変更しますが、そのままでもかまいません。 App.js import logo from './logo.svg'; import './App.css'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Hello, world! </p> </header> </div> ); } export default App; ReactアプリをElectron上で表示する Electronを追加インストールします。 > cd erhello > npm i -D electron 続いて、package.jsonを編集します。 いつも通りエントリーポイントのファイル名を変更します。 加えて、Reactのアウトプットが相対パスで動作するようにhomepageも指定します。 package.json ... "main" : "main.js", "homepage" : "./", ... main.jsは前回のElectron単独のHello,worldで作ったものを使い回します。 今回の変更点は、読み込むindex.htmlのパスをReactのビルド先に合わせることだけです。 main.js const { app, BrowserWindow } = require('electron'); function createWindow () { // ウインドウ作成 const mainWindow = new BrowserWindow({ width: 800, height: 600, }); // index.htmlの内容でウィンドウ表示 mainWindow.loadFile('./build/index.html'); // パス変更 } // Electronの初期化完了時に呼ばれる app.whenReady().then(() => { createWindow(); // Mac用処理 app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }) }); // (Mac以外は)ウインドウが全部閉じられたら終了 app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit(); }); ビルドを実行し、Electronアプリを起動してみます。 > npm run build > npx electron . 次のようにHello world画面が表示されれば成功です。 次回は、Electronのメインプロセスとの通信を試してみたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[React]フォームをエンターキーで送信する方法

はじめに 検索フォームを入力したときに、検索ボタンをわざわざ押すのが面倒だったので、 エンターキーで検索条件を送信する方法を探しました。 やり方 export default function SearchField() { const dispatch = useDispatch(); const [inputText, setInputText] = React.useState(""); const pressEnter = (e: any) => { // ここでエンターキーを指定する if (e.key == "Enter") { dispatch( fetchPresentations({ query: e.target.value, }) ); } }; return ( <Search> <SearchIconWrapper> <SearchIcon /> </SearchIconWrapper> {/* onKeyDownを使用する */} <StyledInputBase placeholder="検索" onKeyDown={(e) => pressEnter(e)} /> </Search> ); } 完成 これで、エンターキーを押すだけで検索することが出来ます。 検索ボタンも必要なくなったので、非表示にしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React-Reduxを基本からまとめてみた【7】【Redux Middleware】

Middlewareとは 『Middleware』は、ActionをdispatchしてからreducerにActionを引き渡すまでの媒介の役割を果たす。全てのdispatchを聞き取り、Actionの詳細や現在の状態を把握してコードを実行する。複数のMiddlewareを組み合わせて新しい機能を追加することも可能で、それぞれMiddlewareが前後の状況を理解する必要はない。 『Middleware』の例としては、非同期リクエストの処理(サーバーへのHTTPコールなど)、ロギング、ルーティングなどがある。 『Middleware』は、主にアプリケーション内の非同期Actionを処理するために使用でき、Reduxでは、副作用や非同期Actionを可能にするミドルウェアライブラリとして、Redux-thunkやRedux-Sagaが有名。 なぜReactのMiddlewareが必要なのか Reduxが同期型である一方で、Reduxが非同期操作でどのように動作するのか疑問に思うかもしれない。Redux Middlewareがその答えで、基本的なReduxStoreがあれば、それは同期的な更新のみを行うことができる。Redux Middlewareは、storeの機能を拡張するのに適したツールで、Redux Middlewareは、reducerの前にdispatchされたアクションと対話するための媒体として機能する。 高次関数を使ってReactでカスタマイズしたMiddlewareを作ることができる。また、Reduxの複数のMiddlewareは、組み合わせることができる。このようにして、新しい機能を追加することができる。ただし、reactのMiddlewareはどれも、前後の知識を必要としない。一言で言えば、reactのMiddlewareはdispatchされたActionとreducerの間に入る。 ReduxのMiddlewareはapplyMiddlewareというAPIにアクセスでき、これにより、reactのカスタムミドルウェアだけでなく、redux-thunkやredux promiseのようなMiddlewareも利用できるようになる。 参考サイト Redux Middleware: A Perfect Beginner’s Guide
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからReact始めたい人のための今日だけでできるTODO#18 useCallback

useCallbackとは? 関数をメモ化するフックです。 React.memoを利用した場合でも親コンポーネントからコールバック関数をpropsで受け取った場合子コンポーネントは再レンダリングされます。 コンポーネントが再レンダリングされるたびにコールバック関数が再生成されるため処理が同じでも新しい関数を生成されているとみなされるからです。 例えば下記のような場合 (※前回のコードをこコンポーネントにpropsで関数を渡す形で修正しました) App.js import React, { useState } from 'react'; import { Counter } from './Counter'; const initialCount = 0; export default function App() { const [countA, setCountA] = useState(initialCount); const [countB, setCountB] = useState(initialCount); const countIncrementA = () => setCountA((prevCountA) => prevCountA + 1); const countIncrementB = () => setCountB((prevCountB) => prevCountB + 1); return ( <> <Counter text='Aボタン' count={countA} countIncrement={countIncrementA} /> <Counter text='Bボタン' count={countB} countIncrement={countIncrementB} /> </> ); }; CoounterコンポーネントにApp.jsで定義したcountIncrementAをpropsで渡すようにして実装してみました。 ボタンをクリックするとconsoleには下記の画像のように表示されます。 ボタンAをクリックすると、ボタンBも反応しています。 useCallbackを利用 定義されている2つの関数をuseCallbackでラップします。 importするのも忘れずに。 App.js import React, { useState, useCallback } from 'react'; export default function App() { const [countA, setCountA] = useState(initialCount); const [countB, setCountB] = useState(initialCount); const countIncrementA = useCallback( () => setCountA((prevCountA) => prevCountA + 1), [countA] ); const countIncrementB = useCallback( () => setCountB((prevCountB) => prevCountB + 1), [countB] ); //以下省略 変更してボタンをクリックすると変更されたコンポーネントしかレンダリングされなくなります。 useCallback()でメモ化されたコールバック関数をReact.memo()でメモ化された子コンポーネントへpropsで渡されることで不要な再レンダリングをスキップさせることができます。 どちらか1つでは機能しないので。useCallback()とReact.memo()は2つで1つということを覚えておくと良いと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む