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

async/awaitで非同期処理の完了を待つ

①非同期処理をおこなう関数を宣言

const 関数名 = async () => {
  const message = 'GitのユーザーIDは';
  const url = 'https://api.github.com/users/taizo-pro'

②awaitをつけ、fetchが実行完了するまで次に進まなくさせる

// jsonにreturnされた値が入る    
const json = await fetch(url)
      .then(res => {
          console.log('非同期処理成功時のメッセージです')
          return res.json()
      }).catch(error => {
          console.error('非同期処理失敗時のメッセージです。', error)
          return null
      });

const username = json.login;
  console.log(message + username)
}
関数名()
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CORS(preflight request)にハマったけど解決した話

CORS(preflight request)にハマったので、解決方法を備忘録として残しておきます。

エラーが起きた場面

異なるドメインからHttpリクエストを送る場合は、CORSに注意だよなぁ。
サーバー側のレスポンスで、ヘッダーをつけてあげれば良いんだろう。
簡単じゃん。

クライアント側

何かしらのデータをjasonでPOSTする。

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", API_ENDPOINT);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send(JSON.stringify(data));

APIサーバー側

サーバー側では、レスポンスのヘッダーを付けてあげる。

func (a *API) HandleFunc(w http.ResponseWriter, r *http.Request) {
    //略...

    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")

    //略...

    fmt.Fprint(w, "ok")
}

結果、エラー...!

当然、結果が正常に返ってくると思いきや
プリフライトリクエスト?がどうのこうのといったエラーが出た。。。なんやこれ。。。

Access to XMLHttpRequest at 'http://localhost:8080/api' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

CORS(preflight request)エラー解決

preflight requestとは?

リクエストによっては CORS プリフライトを引き起こさないものがあります。これをこの記事では「単純リクエスト」と呼んでいますが、 (CORS を定義している) Fetch 仕様書ではこの用語を使用していません。 「単純リクエスト」は、以下のすべての条件を満たすものです。
・許可されているメソッドのうちの一つであること。
GET
HEAD
POST
・ユーザーエージェントによって自動的に設定されたヘッダー (たとえば Connection、 User-Agent、 または Fetch 仕様書で「禁止ヘッダー名」として定義されているヘッダー) を除いて、手動で設定できるヘッダーは、 Fetch 仕様書で「CORS セーフリストリクエストヘッダー」として定義されている以下のヘッダーだけです。
Accept
Accept-Language
Content-Language
Content-Type (但し、下記の要件を満たすもの)
DPR
Downlink
Save-Data
Viewport-Width
Width
・Content-Type ヘッダーでは以下の値のみが許可されています。
application/x-www-form-urlencoded
multipart/form-data
text/plain
・リクエストに使用されるどの XMLHttpRequestUpload にもイベントリスナーが登録されていないこと。これらは正しく XMLHttpRequest.upload を使用してアクセスされます。
・リクエストに ReadableStream オブジェクトが使用されていないこと。
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#Preflighted_requests

上記の条件を満たさないものはpreflight requestがメインのリクエストの前に行われます。
今回は、POSTですが、"Content-Type", "application/json"をヘッダーに付けているので、プリフライトリクエストが起きました。
画像の最初のリクエストがpreflight requestです。
ここでは、実際にはOPTIONSメソッドがpreflight requestとして走ります。
preflight_correct.png

解決方法

 OPTIONSメソッドの時は、http.StatusOKを返すようにしたら解決しました!

func (a *API) HandleFunc(w http.ResponseWriter, r *http.Request) {
    //略...

    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")

    if r.Method == "OPTIONS" {
        w.WriteHeader(http.StatusOK)
        return
    }
    //略...

    fmt.Fprint(w, "ok")
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactでエラーメッセージを表示する

プログラミングの勉強日記

2020年6月24日 Progate Lv.148
React Ⅳ
 前回の記事 で作成した問い合わせフォームにエラーメッセージを表示させる。今回は簡単なエラーメッセージを作成する。

入力内容をstateで管理する

 入力に合わせてエラーメッセージを表示する処理を作る。エラーメッセージは文字を入力してから入力値が空ならエラーが表示されるようにする。

1.stateでinputの準備

 Reactでフォームを作る場合、stateと入力値を紐づける。メールアドレスの入力値を管理するstateのemailを用意して、inputタグのvalue属性にstateの値を指定する。

ContactForm.js
  super(props);
  this.state={
    ...
    email:'', //入力値を管理するstateを準備
  };
  return(
    {/* value属性にstateの値を指定。フォームの入力欄にstateの値が表示される */}
    <input value={this.state.email} />
  );

2.入力イベントの取得

 このままだと入力できないので入力できるようにする。
 フォームの入力や削除が行われたときに処理を実行するにはonChangeイベントを使う。

ContactForm.js
<input onChange={()=>{/*処理*/}} />

 入力値の取得はonChangeイベントの関数にeventという引数を追加してevent.target.valueで取得する。

ContactForm.js
<input 
  value={this.state.email}
  onChange={(event)=>{console.log(event.target.value)}}
/>

3.stateの更新

 handleEmailChangeメソッドを作ってstateの更新を行う。

ContactForm.js
handleEmailChange(event){
  const inputValue=event.target.value;  //2.入力値を取得
  this.setState({email:inputValue});  //3.入力値でstateを更新
}
...
retuen(
  <p>メールアドレス</p>
  <input 
    value={this.state.email}
    onChange={(event)=>
      {/* 1.eventを引数に渡してメソッドを呼び出す */}
      {this.handleEmailChange(event)}
    } 
  >
);

エラーメッセージの作成

 入力欄に文字を入力してから文字の入力を全て消したときにエラーメッセージが出るようにする。入力値が空かどうかをstateで管理する。stateで新たにhasEmailErrorという真偽値型のstateを定義する。

ContactForm.js
constructor(props){
  super(props);
  this.state={
    ...
    hasEmailError:false,
  };
}

 hasEmailErrorがtrueのとき変数emailErrorTextにエラー部分のJSXを代入して表示する。

ContactForm.js
render(){
  let emailErrorText;
  if(this.state.hasEmailError){
    emailErrorText=(
      <p>メールアドレスを入力してください</p>
    );
  }
  ...
  return(
    <p>メールアドレス(必須)</p>
    <input 
      value={this.state.email}
      ...
      {emailErrorText}

 エラーメッセージを表示する。入力値と空文字列('')を比較して、isEmptyに代入する。複数のstateを更新する場合、コンマ(,)で区切り一度のsetStateでまとめて変更することができる。

ContactForm.js
handleEmailChange(event){
  const inputValue=event.target.value;
  const isEmpty=inputValue==='';
  this.setState({
    email:inputValue,
    hasEmailError:isEmpty,
  });
}

問い合わせフォームでエラーメッセージの表示

ContactForm.js
import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false,
    };
  }

  handleEmailChange(event) {
    const inputValue = event.target.value;
    const isEmpty=inputValue==='';

    this.setState({
      email:inputValue,
      hasEmailError:isEmpty,
    });

  }

  handleSubmit() {
    this.setState({isSubmitted: true});
  }

  render() {
    let emailErrorText;
    if (this.state.hasEmailError) {
      emailErrorText = (
        <p className='contact-message-error'>
          メールアドレスを入力してください
        </p>
      );
    }

    let contactForm;
    if (this.state.isSubmitted) {
      contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>
      );
    } else {
      contactForm = (
        <form onSubmit={() => {this.handleSubmit()}}>
          <p>メールアドレス(必須)</p>
          <input
            value={this.state.email}
            onChange={(event) => {this.handleEmailChange(event)}}
          />
          {emailErrorText}
          <p>お問い合わせ内容(必須)</p>
          <textarea />
          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

    return (
      <div className='contact-form'>
        {contactForm}
      </div>
    );
  }
}

export default ContactForm;

 ここまで紹介した例ではメールアドレスのエラーメッセージの表示であったが、問い合わせ内容も同様の手順でエラーメッセージを表示させることができる。

ContactForm.js
import React from 'react';

class ContactForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      email: '',
      hasEmailError: false,
      content:'',
      hasContentError:false,

    };
  }

  handleEmailChange(event) {
    const inputValue = event.target.value;
    const isEmpty = inputValue === '';
    this.setState({
      email: inputValue,
      hasEmailError: isEmpty,
    });
  }

  handleContentChange(event){
    const inputValue=event.target.value;
    const isEmpty=inputValue==='';
    this.setState({
      content:inputValue,
      hasContentError:isEmpty,
    });
  }

  handleSubmit() {
    this.setState({isSubmitted: true});
  }

  render() {
    let emailErrorText;
    if (this.state.hasEmailError) {
      emailErrorText = (
        <p className='contact-message-error'>
          メールアドレスを入力してください
        </p>
      );
    }

    let contentErrorText;

    if(this.state.hasContentError){
      contentErrorText=(
        <p className='contact-message-error'>
          お問い合わせ内容を入力してください
        </p>
        );
    }

    let contactForm;
    if (this.state.isSubmitted) {
      contactForm = (
        <div className='contact-submit-message'>
          送信完了
        </div>
      );
    } else {
      contactForm = (
        <form onSubmit={() => {this.handleSubmit()}} >
          <p>メールアドレス(必須)</p>
          <input
            value={this.state.email}
            onChange={(event) => {this.handleEmailChange(event)}}
          />
          {emailErrorText}
          <p>お問い合わせ内容(必須)</p>
          <textarea 
            value={this.state.content}
            onChange={(event)=>{this.handleContentChange(event)}}
          />
          {contentErrorText}


          <input
            type='submit'
            value='送信'
          />
        </form>
      );
    }

    return (
      <div className='contact-form'>
        {contactForm}
      </div>
    );
  }
}

export default ContactForm;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gatsby + microCMS + Firestore エラー・不具合集

Gatsby + microCMS + Firestore エラー・不具合集

microCMSからGraphQLでもらってくる記事コンテンツが…

10を超えるとそれ以上取得できない。

原因

microCMSのGET APIはデフォルトで10件まで取得となっている。

解決方法

limitパラメータを与えることで取得件数を増やすことができる。
Gatsbyの場合は、gatsby-config.jsでオプションで変更する。

// gatsby-config.js
   resolve: "gatsby-source-microcms",
    options: {
      apiKey: "xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxx",
      serviceId: "hogehoge",
      endpoint: "articles",
      query: {
        limit: 100, // ←ここで100件に変更
      }
   },

同一ページをリロードすると中身が表示されない

gatsby developの開発環境では問題ない。しかしgatsby buildの本番環境でページ再読み込みするとコンテンツが表示されない。エラーもなし。

原因

Gatsbyの問題。以下のコード、dangerouslySetInnerHTMLのバグ。

<p
         dangerouslySetInnerHTML={{
           __html: `${article.body}`,
         }}
></p>

解決方法

まだIssue上がりっぱなしだが、回避策として<div>を使う。<p>タグだと起きる問題なのであった。

<div
         dangerouslySetInnerHTML={{
           __html: `${article.body}`,
         }}
></div>

参考:dangerouslySetInnerHTML does not work on production builds


Firestoreのタイムスタンプ型フィールドの表示方法

Firestoreの日付フィールドに現在時間を書き込むとき、
createdat : new Date()
とか
createdat : firebase.firestore.Timestamp.fromDate(new Date())
とかやって書き込むと思うが自動的にタイムスタンプ型(Timestamp型)で書き込まれる。これを読むとき、{item.created}とやってもエラー。

原因

Firestoreの日付型フィールドの仕様が変わった。

解決方法

つぎのようにして読む。

{new Date(item.createdat.seconds * 1000).toLocaleDateString("ja-JP")} {new Date(item.createdat.seconds * 1000).toLocaleTimeString("ja-JP")}

これでこんな風になる。
image.png

TypeError: unsubscribe is not a function

Firestoreからデータを読み込むとき、必ずuseEffect()の中でunsubscribe();すると思う。以下はコード例。

// components/comments.js
import React, { useEffect, useState } from 'react'
import firebase from '../../utils/firebase'

const useComments = () => {
      const [items, setItems] = useState([]);

      useEffect(() => {
          const unsubscribe = firebase
          firebase
            .firestore()
            .collection("comments")
            .onSnapshot(snapshot => {
              const data = []
              snapshot.forEach(d => data.push({
                  id: d.id,
                  ...d.data(),
                }));
                setItems(data)
            });
          return () => unsubscribe(); // ← ここ
      }, []); 
      return items;
};

const CommentList = () => {
・・・表示処理・・・
}

常套句だと思う。このコンポーネントを例えば全ページに埋め込んで表示させたいとする。例えばこのように。

//すべてのページ.js
import React from "react"
import CommentList from '../components/Comment'

const AllPages = () => {
 return (
・・・略・・・
 <CommentList />  ここ
 )
}

これですべてのページにコメントリストコンポーネントが表示される。しかしこれで他のページに遷移すると
image.png

原因

わからない。静的サイトだから?

解決方法

unsubscribe()しない。
return () => unsubscribe();の一文をコメントアウト。

これでいいのだろうか…。結論から言うとGatsbyで動的機能は原則きびしい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactideを使ってみる

最近、Reactに入門してサーバーサイドエンジニアからフロントエンドエンジニアに転向できなかと試行錯誤しています。

そのなかで同僚にReactideってどうなの?と聞かれたのでちょっと調べて使ってみました。

Reactide:公式

環境:Ubuntu18.04
install方法は公式にあります。

まずは、git cloneします。
その後、公式の手順(以下)通り進めていきます。
みた感じスムーズにできそうなのですが、いくつかはまりポイントがありました。

手順
git checkout 3.0-release
npm install
npm run webpack-production
npm run electron-packager

嵌りポイント1

npm run webpack-production

エラーでwebpackが失敗しました。

error
    Error: Cannot find module 'monaco-editor\esm\vs\editor\contrib\gotoSymbol\goToCo
    mmands'

どうやらissueとしても上がっているようで、そこに解決方法が載っていました。
公式のissue

cloneしたpackege.jsonを修正します。

package.json
"monaco-editor": "^0.14.3",
"monaco-editor-webpack-plugin": "^1.5.4",

↑を↓のように修正

package.json
"monaco-editor": "~0.14.3",
"monaco-editor-webpack-plugin": "~1.5.4",

嵌りポイント2

electron-packager

error
12 info lifecycle reactide@3.0.0~electron-packager: Failed to exec electron-packager script
13 verbose stack Error: reactide@3.0.0 electron-packager: `electron-packager . --overwrite --platform=darwin --arch=x64 --icon=/Users/ep/Codesmith/reactide/icons/icon.png --prune=true --out=release-builds`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack     at EventEmitter.emit (events.js:198:13)
13 verbose stack     at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:198:13)
13 verbose stack     at maybeClose (internal/child_process.js:982:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid reactide@3.0.0

エラーを読むと、--platform=darwinと出力されていました。
このスクリプト、MacOS用???
という事で、package.jsonの以下の箇所を修正します。

package.json
"electron-packager": "electron-packager . --overwrite --platform=darwin --arch=x64 --icon=/Users/ep/Codesmith/reactide/icons/icon.png --prune=true --out=release-builds"

↑を↓へ修正

package.json
"electron-packager": "electron-packager . --overwrite --platform=linux --arch=x64 --icon=/Users/ep/Codesmith/reactide/icons/icon.png --prune=true --out=release-builds"

--platform=darwin--platform=linux

これで全てのコマンドが通りました。

おさらいですが、

Reactideのclone用フォルダを作成
git cloneする
cloneしたフォルダに入って、package.jsonを2か所修正する(Ubuntuの場合)
その後、以下のコマンドを順次実行
npm install
npm run webpack-production
npm run electron-packager

完了後、release-builds > Reactide-linux-x64 直下にReactideという実行ファイルが生成されているので実行

WS000001.JPG

実行するとこんな画面が表示されます。
WS000002.JPG

では開発していきます。
まずは File > New Projectでプロジェクトを作成
※私がはまったのですが、Ubuntuでプロジェクトを作成するときに、既存のフォルダを指定すると作成できませんでした。必ず、パネル上部のinputエリアから新規プロジェクト名を入力してフォルダを作成する必要がありました

プロジェクト作成が完了するともう一つReactideが起動しますが、落としてしまって構いません。

WS000003.JPG

作成後、projectに手持ちのソースを突っ込んで動かしてみます。

実行方法は他のと基本的に変わりません。
ターミナル開いて

command
npm start

その後、ブラウザでhttp://3000あたりにつなぎましょう。

で、使ってみた感想ですが、、、
これからに期待。

※terminalやシミュレーターを起動するのは右上のアイコンたちです。

WS000005.JPG

時々プロジェクトの進捗を覗きに行こうとは思いました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】apiから jsonデータを取得してブラウザに表示する方法

今回は、テーマ通り、Reactを使って、apiからJsonを取得→表示を実施。
都度都度reactで使う基本をまとめてみました。参考までに。。

今回使うapiは無料でEuroベースの為替情報を取得できるこちらを使用。
https://api.exchangeratesapi.io/latest

今回はこのapiのjsonデータをブラウザに表示するところまでを紹介します。

DEMOはこちら

実装手順

①index.htmlにid="root"を用意
②index.jsを用意。(下処理)
③ ②の中に処理を記述。(api→json取得 + 表示)
という流れで行きます。

index.htmlにid="root"を用意

デフォルトでindex.htmlにあると思います。今回はindex.jsに記述しますが、試し書きならApp.jsでもok。

index.jsを用意

大枠はこちら。

index.js
import React, { Component } from 'react';
import { render } from 'react-dom';


class Exchange extends Component {
  constructor(props) {
    super(props);
    this.state = {
      //stateを書く場所
    };
  }
  componentDidMount() {
    fetch("")//apiをここに記述
      //jsonをひっぱりだすところ
  }

  render() {
    var {  } = this.state; //state内容を変数へ
    //処理を書く場所
  }
}

export default Exchange;

render(<Exchange />, document.getElementById('root')); //id="root"に反映

[補足説明]
・Exchangeクラスコンポーネントに最初constructor(props)なるものがあります。これはstateを初期化する唯一の場所でsuper(props)で親クラスのコンストラクタを参照(ここではextendsされたComponent)するためのものです。propsとは 親コンポーネントから渡されたプロパティで、一般的に、親コンポーネントから子コンポーネントに渡される値として使われます。stateはそのコンポーネント自体によって保持されるものなので、親から子へみたいな事はできません。
こちらにめちゃんこわかりやすくpropsとstateを紹介している記事があるので参考までに。
https://qiita.com/rio_threehouse/items/7632f5a593cf218b9504

・componentDidMount()はRender直後に行いたい処理を書く時などに使います。
こちらも詳しい説明や類例が下記Urlに紹介されているので参考までに。
https://qiita.com/sekikawa_a/items/8ab70f457ef73871419f

②の中に処理を記述。(api→json取得 + 表示)

index.js
import React, { Component } from 'react';
import { render } from 'react-dom';

class Exchange extends Component {
  constructor(props) {
    super(props);
    this.state = { //state初期化
      isLoaded: false,
      items: []
    };
  }
  componentDidMount() { //render直後に行いたい処理を書くところ
    fetch("https://api.exchangeratesapi.io/latest") //api
      .then(res => res.json()) 
      .then(json => {
        console.log(json.rates);
        this.setState({
          isLoaded: true,
          items: json.rates
        });
      });
  }

  render() {
    var { items, isLoaded } = this.state;
console.log(items);
    if (!isLoaded) {
      return <div>...Loading</div>;
    } else {
      return (
        <div>
          <ul>
            {Object.keys(items).map(key => (
              <li key={key}>{key} - {items[key]}</li>
            ))}
          </ul>
        </div>
      );
    }
  }
}

export default Exchange;

render(<Exchange />, document.getElementById('root'));

[補足説明]
・まず最初にReactサイクルに基づいて、初期ステートをconstructorにセットしておきます。itemsというステートは配列宣言してあげましょう。そのあと、componentDidMount()でリクエストやレスポンスといった HTTP のパイプラインを構成する要素を操作できるfetchを使います。res オブジェクトから JSON を抽出するには、 json() メソッドを使用する必要があるので、json欲しかったらちゃんと書きましょう。

・あとはconsole.logでjsonが取得されているのを確認して、steta更新をするthis.setState({})のitemsにjson.ratesと書いてあげましょう。ちなみにisLoadをstateに記述する理由は、render()時のif処理で取得できているか否かを示すためです。なので、setState({})をrenderに反映するために、いったんvar { items, isLoaded } = this.state;のように変数宣言しておきましょう。

・最後に

{Object.keys(items).map(key => (
              <li key={key}>{key} - {items[key]}</li>
            ))}

と書いていますが、
これはObject.key()メソッドで引数にitemsを入れる事でプロパティを取得しています。次にmap()を用いて、配列として返し、keyにはapiの国コードが、items[key]には為替レートが出るように記述しています。
Object.key()やmap()について知りたい方はこちらを参考にしてみてください。
https://www.sejuku.net/blog/64361

以上、雑ですがapiからjsonを取得→データ表示できます。

まとめ

今回は簡単なjsonデータの取得から表示まで紹介しました。
次回はfirebaseとreactの連携でも紹介してみようかなと思います。

読んでくれてありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React学習 Webpackその1

Webpackとは

Webpackとは、JavaScriptCSSなどのソースファイルを1つにまとめたり、JSXのような特殊な記法のファイルを変換するツールです。
ソースファイルをまとめることで、ウェブページのHTTPリクエストの数を減らしたり、高度なウェブアプリケーションの開発に利用できます。

環境構築

ディレクトリ作成

mkdir webpacktest

ディレクトリ移動

cd webpacktest

npmの初期化

npm init -y

webpackのインストール
webpack: webpack本体
webpack-cli: コマンドライン操作用

npm i -D webpack webpack-cli

起点となるソースファイル配置

/src/index.js
import {mul} from './mul'
const result = mul(5, 6)
console.log(result)
/src/mul.js
export function mul (a, b) {
  return a * b
}

webpackを実行し、ファイルをまとめ上げる
特にwebpackの設定を行っていない場合は、デフォルトの起点となるディレクトリとファイル名は/src/index.jsであり、出力されるディレクトリとファイル名は/dist/main.jsとなります。
この状態だと設定は行っていないので、WARNING in configurationが発生します。

npx webpack 

設定構築

実行はできましたが、このままだとまともに使えないので、各設定を行っていきます。

npmからの実行

まずは、npmからビルドできるようにpackage.jsonを修正します。

package.json
{
  "name": "webpacktest",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
   //buildの追加
   "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1"
  }
}

これにより以下のコマンドでビルドの実行が行えます。

npm run build

webpackの設定ファイル作成

変換元のファイル名等の設定を行うには、設定用のファイルを作成します。
ファイル名はwebpack.config.jsです。

entry: 変換元パス
output: filename=変換先ファイル名、path=変換先のファイルを配置するパス

webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'out')
  }
};

また、modeという設定もあり、開発用のdevelopmentとソースを変換する際に最適化を行うproductionがあります。
以下のように設定することで、ビルド時に反映されます。

webpack.config.js
const path = require('path');

module.exports = {
  //modeオプションの追加
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'out')
  }
};

ただ、毎回modeを書き換えるのは大変なため、package.jsonにmodeを記述します。

webpack.config.js
const path = require('path');

module.exports = ( env, argv ) => ({
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'out')
  }
});
package.json
{
  "name": "webpacktest",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    //本番用ビルドコマンド
    "build": "webpack --mode=production",
    //開発用ビルドコマンド
    "build-dev": "webpack --mode=development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  }
}

これにより、以下のコマンドでmode切り替えが可能となります。

本番用
npm run build
開発用
npm run build-dev

ファイル監視

ファイルを編集する度に、手動でビルドし直すのは大変なので、ファイルを監視し自動的に変換を行ってくれるように設定します。
以下のどれか設定することで監視が可能となります。

①webpack.config.jsで設定する場合

webpack.config.js
const path = require('path');

module.exports = ( env, argv ) => ({
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'out')
  },
  //watchの追加
  watch: true
});

②package.jsonで設定する場合

package.json
{
  "name": "webpacktest",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "build": "webpack --mode=production",
    //watchオプション追加
    "build-dev": "webpack --mode=development --watch"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  }
}

③専用の開発用webサーバで監視する場合

webpack-dev-serverパッケージをインストール
npm i -D webpack-dev-server
webpack.config.jsの編集
const path = require('path');

module.exports = ( env, argv ) => ({
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'out')
  },
  //devServerの追加
  devServer: {
    //ドキュメントルート設定
    contentBase: path.resolve(__dirname, 'out'),
    //監視モード設定
    watchContentBase: true,
    //ポート設定
    port: 3000
  }
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React初心者が試行錯誤しながらサイト作ってみた(その1)

つまずいた部分のメモ

Material-UIはどうやってスタイル変えるの!?

パッと(これが原因で後でエラーが...)調べたところmakeStyleswithStylesが出てきた

今回はmakeStylesを使うことにしました.

makeStyles が使えない事件!!

早速使って見たら以下のエラーが,,,

Header.js
const useStyles = makeStyles({
  title: {
    flexGrow: 1,
  },
});
export default class Header extends.React.Component() {
  render (){
    const classes = useStyles();//Error
    return (...);
  }
}

ちゃんと公式サイトで調べたらmakeStylesはフックAPIだということが判明! <-- ちゃんと調べろ自分
というわけで関数コンポーネントに変更したらできました.

Header.js
const useStyles = makeStyles({
  title: {
    flexGrow: 1,
  },
});
export default function Header() {
  const classes = useStyles();//OK
  return (...);
}

その他のスタイル変更

Header.js
//style={{...: ...}}で各種変更可
<AppBar style={{ background: '#d1c4e9' }}>//AppBarの背景の色変更
<MenuIcon style={{ color: purple[800]}}>//MenuIconの色変更
//makeStylesを実際に適用
const useStyles = makeStyles({
  title: {
    flexGrow: 1,
  },
});
export default function Header() {
  const classes = useStyles();
  return (
     <Typography variant="h6" className={classes.title}>//適用
       Title
     </Typography>
  );
}

次はTeitterとGithubのアイコン表示や,メニューボタン押したら一覧が出てくる機能を追加してみます.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む