HighBridge’s blog

勉強の記録

Docker

Docker メモ

Dockerのコマンド

docs.docker.jp

気になるところのメモ

ポート
  • -p ホストのポート番号:コンテナのポート番号の形式。 -p 8080:80でブラウザがポート8080番にアクセスすると、コンテナのポート80番に転送されてそこで公開されている内容が見えるようになる。
マウント設定
  • -v ホストのディレクトリ:コンテナのディレクトリの形式。 -v "$PWD":/usr/local/apache2/htdocs/は$PWDがdockerコマンドを入力した瞬間の、ホスト側のカレントディレクトリを示す環境変数。それがapacheのwebコンテンツを公開するディレクトリに割り当てられるので、dockerコマンドを入力するディレクトリにindex.htmlを置くとそのページが表示されることになる。

※ マウントとは、あるディレクトリに対して別のディレクトリを被せて、そのディレクトリの内容が見えるようにする設定のこと。

Dockerfileの記述

docs.docker.jp

Node.js 環境

Node.js 環境まとめ

  • anyenvを利用してNode.jsのバージョンを管理。
  • 必要なバージョンはすぐに切り替えることが可能。
  • anyenvで色々なバージョンを管理できるので、nodenvの最新バージョンがなかった場合には、更新をしないといけないので、下の記事のように更新をすること。 qiita.com

2021/8/20

今日のメモ

企業面接

  • インターン面接のフィードバックで口頭での研究の説明ができるようにしておいた方がいい。またweb系の経験を積んでおいた方がいい。本などから知識を得る姿勢は現状ではいい。
  • 選考が12月から1月にエントリーをしておく必要がある。その辺りがピークで7、8割は取るらしいので早めに行動すること、調査すること、準備することが大事。

コーディングテスト

  • コマンドラインの作成とか、入出力をファイルで行う形式などがあるのでその辺りにも慣れておく必要がある。

Node.js + React

  • expressに入った
  • 環境の構築
  • Photon kitのインストールができない
npm install connors/photon --save
  • 途中で止まるのでとりあえずコードだけ書いてから後から環境を整える。
  • nodeの最新バージョンで上のコマンドを実行したらインストールできたけど、npmのバージョンが古くなっているのが心配。
  • 実行までできたが、何も描画されていない。

2021/8/19

React + Node.js

フォーム部品の扱い

テキストボックス

import React from 'react'
import ReactDOM from 'react-dom'

class TextForm extends React.Component {
  constructor(props){
    super(props)
    this.state = { value: '' }
  }

  render () {
    // フォームにテキストボックスを指定
    return (
      <div>
        <form onSubmit={e => this.doSubmit(e)}>
          <input type='text'
            onChange={e => this.doChange(e)}
            value={this.state.value} />
          <input type='submit' />
        </form>
      </div>
    )
  }
  // テキストボックスを変更したとき
  doChange (e) {
    this.setState({ value: e.target.value })
  }

  // フォームを送信した時
  doSubmit (e) {
    e.preventDefault()
    window.alert(this.state.value)
  }
}

ReactDOM.render(
  <TextForm />,
  document.getElementById('root')
)

チェックボックス

import React from 'react'
import ReactDOM from 'react-dom'

class CBoxForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = { check: true }
  }

  render() {
    // フォームにチェックボックスを指定
    return ( <div>
      <form onSubmit={e => this.doSubmit(e)}>
        <label>
          <input type="checkbox"
            onChange={e => this.doChange(e)}
            checked={this.state.check} 
            />食べる
        </label><br />
        <input type="submit" value='決定' />
      </form>
    </div>) 
  }

  // チェックボックスをクリックした時
  doChange (e) {
    this.setState({ check: !this.state.check })
  }

  // フォームを送信した時
  doSubmit (e) {
    e.preventDefault()
    window.alert(this.state.check ? '食べる' : '食べない')
  }
}

ReactDOM.render(
  <CBoxForm />,
  document.getElementById('root')
)

テキストエリア

import React from 'react'
import ReactDOM from 'react-dom'

class TextAreaForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = { value: 'Hello' }
  }

  render () {
    // フォームにテキストエリアを指定
    return ( <div>
      <form onSubmit={e => this.doSubmit(e)}>
        <textarea
          onChange={e => this.doChange(e)}
          value={this.state.value}
          /><br />
        <input type="submit" value='決定'/>
      </form>
    </div>)
  }

  // テキストエリアを変更したとき
  doChange (e) {
    this.setState({ value: e.target.value })
  }
  // フォームを送信した時
  doSubmit (e) {
    e.preventDefault()
    window.alert(this.state.value)
  }
}

ReactDOM.render(
  <TextAreaForm />,
  document.getElementById('root')
)

ラジオボタン

import React from 'react'
import ReactDOM from 'react-dom'

class TextAreaForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = { value: 'Hello' }
  }

  render () {
    // フォームにテキストエリアを指定
    return ( <div>
      <form onSubmit={e => this.doSubmit(e)}>
        <textarea
          onChange={e => this.doChange(e)}
          value={this.state.value}
          /><br />
        <input type="submit" value='決定'/>
      </form>
    </div>)
  }

  // テキストエリアを変更したとき
  doChange (e) {
    this.setState({ value: e.target.value })
  }
  // フォームを送信した時
  doSubmit (e) {
    e.preventDefault()
    window.alert(this.state.value)
  }
}

ReactDOM.render(
  <TextAreaForm />,
  document.getElementById('root')
)

セレクトボックス

import React from 'react'
import { ReactDOM } from 'react-dom'

class SelectForm extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      items: props.items,
      value: props.value
    }
  }
  render () {
    // セレクトボックスの選択肢を生成
    const options = this.state.items.map( i => {
      return( <option key={i}
        value={i}> {i}
        </option>)
    })
    
    // フォームにセレクトボックスを指定
    return( <div>
      <form onSubmit={e => this.doSubmit(e)}>
        <select 
          value={this.state.value}
          onChange={e => this.doChange(e)}>
            {options}
        </select><br />
        <input type="submit" />
      </form>
    </div>)
  }
  
  // セレクトボックスを変更した時
  doChange (e) {
    this.setState({ value: e.target.value })
  }

  // フォームを送信した時
  doSubmit (e) {
    e.preventDefault()
    window.alert(this.state.value)
  }
}

ReactDOM.render(
  <SelectForm 
    items={['チョコ', '梅干し', 'ラムネ']}
    value='ラムネ' />,
  document.getElementById('root')
)

2021/8/18

Node.js + React

メモ

  • 3-5から開始
  • 正規表現は勉強しといた方が良さそう。
  • プロパティの型の定義を学んだ
  • FormInputというコンポーネントで、valueとnameとfilter, onChangeという4つのプロパティを利用できるものとする例
// コンポーネントの定義 
class FormInput extends Component {...}

// PropTypes型を使うための宣言
import PropTypes from 'prop-types'

// プロパティの型の宣言
FormInput.propTypes = {
  value: PropsTypes.string, // 文字列型
  name: PropsTypes.string.isRequired, // 文字列型で指定が必須
  filter: PropsTypes.object, // オブジェクト型
  onChange: PropTypes.func // 関数型
} 

FormInput.defaultProps = {
  filter: null,
  pattern: null,
  value: '',
  onChange: null
}
import React, {Component} from 'react'
import PropTypes from 'prop-types'

// 汎用的な入力コンポーネント
export default class FormInput extends Component {
  constructor (props) {
    super(props)
    const v = this.props.value
    this.state = {
      value: v,
      isOK: this.checkValue(v)
    }
  }

  // パターンに合致するかチェック
  checkValue (s) {
    if (this.props.pattern === null) {
      return true
    }
    return this.props.pattern.test(s)
  }

  // 値がユーザーにより変更された時
  handleChange (e) {
    const v = e.target.value
    // フィルタが変更されていればフィルタを適用する
    const filter = this.props.filter
    let newValue = v
    if (filter !== null){
      newValue = newValue.replace(filter, '')
    }
    const newIsOK = this.checkValue(newValue)
    this.setState({
      value: newValue,
      isOk: newIsOK
    })
    // イベントを実行する
    if(this.props.onChange) {
      this.props.onChange({
        target: this,
        value: newValue,
        isOK: newIsOK,
        name: this.props.name
      })
    }
  }
  
  // プロパティが変更された時
  componentWillReceiveProps (nextProps) {
    this.setState({
      value: nextProps.value,
      isOK: this.checkValue(nextProps.value)
    })
  }

  //描画
  render () {
    const msg = this.renderStatusMessage()
    return (<div>
      <label>{this.props.label}: <br />
        <input type="text"
          name={this.props.name}
          placeholder={this.props.placeholder}
          value={this.state.value}
          onChange={e => this.handleChange(e)} />
        {msg}
      </label>
    </div>)
  }

  renderStatusMessage() {
    const so = {
      margin: '8px',
      padding: '8px',
      color: 'white'
    }
    let msg = null
    if (this.state.isOK){
      so.backgroundColor = 'green'
      msg = <span style={so}>OK</span>
    } else {
      if (this.state.value !== ''){
        so.backgroundColor = 'red'
        msg = <span style={so}>NG</span>
      }
    }
    return msg
  } 
}

// プロパティの型を定義
FormInput.propType = {
  name: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  filter: PropTypes.object,
  pattern: PropTypes.object,
  value: PropTypes.string,
  placeholder: PropTypes.string,
  onChange: PropTypes.func
}

// プロパティの初期値を定義
FormInput.defaultProps = {
  filter: null,
  pattern: null,
  value: '',
  placeholder: '',
  onChange: null
}
  • DOMにReactで直接アクセスするにはrefプロパティを使う。このプロパティには、コールバック関数を指定するのだが、ReactがDOMを直接インスタンス化する際に実行される。コールバック関数が実行されるとき、インスタンス化したDOMオブジェクトが引数として得られる。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <script src="https://unpkg.com/react@15/dist/react.min.js"></script>
  <script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    // フォームコンポーネント
    class LoginForm extends React.Component {
      constructor (props){
        super(props)
        this.state = {
          user: '',
          pass: ''
        }
      }

      render() {
        const doSubmit = e => this.doSubmit(e)
        const doChange = e => this.doChange(e)
        // 描画内容
        return (<form onSubmit={doSubmit}>
          <label>ユーザー名: <br />
            <input type="text" name="user"
              ref={ (i)=>{ this.user = i} }
              value={this.state.user}
              onChange={doChange} />  
          </label><br />
          <label>パスワード: <br />
            <input type="text" name="pass"
              ref={ (i)=>{ this.pass = i} }
              value={this.state.pass}
              onChange={doChange} />  
          </label><br />
          <input type="submit" value="送信" />
        </form>)
      }

      doChange (e) {
        const key = e.target.name
        this.setState({
          [key]: e.target.value
        })
      }

      // refプロパティで要素を取得しているのでthis.userでDOMにアクセスできる
      doSubmit (e) {
        e.preventDefault()
        // 値が空の場合にinput要素をフォーカス
        if (!this.state.user) {
          this.user.focus()
          return
        }
        if (!this.state.pass) {
          this.pass.focus()
          return
        }
        window.alert(JSON.stringify(this.state))
      }
    }
    // DOMを書き換え
    ReactDOM.render(
      <div><LoginForm /></div>,
      document.getElementById('root')
    )
  </script>
  
</body>
</html>
  • コンポーネントのrender()メソッドで返すオブジェクトは実際に、DOMに描画されるオブジェクトとは全く関係がない。Reactはrender()メソッドの戻り値を元にして、実際のDOMを生成するので、戻り値はDOMオブジェクトではないことに注意。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <script src="https://unpkg.com/react@15/dist/react.min.js"></script>
  <script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    class MyCompo extends React.Component {
      constructor(props){
        super(props)
        this.state = {value: ''}
      }

      render() {
        this.preInput = <input
          type="text"
          ref={i => { this.realInput = i }}
          onClick={e => this.doClick(e)} />
        
        return (
          <div>{this.preInput}</div>
        )
      }

      doClick (e) {
        // 合致するか
        console.log(this.preInput)
        console.log(this.realInput)
        if (this.preInput === this.realInput) {
          console.log('同じ')
        }else{
          console.log('異なる')
        }
      }
    }

    // DOMを書き換え
    ReactDOM.render(
      <div><MyCompo /></div>,
      document.getElementById('root')
    )

  </script>
  
</body>
</html>

SuperAgent(Ajax通信をするライブラリ)の使い方

  1. SuperAgentのライブラリを取り込む
  2. request.get(url).end(callback)を呼ぶ
  3. データを取得した時のコールバック関数を記述
// 機能を取り込み
const request = require('superagent')

// 指定のURLからデータを取得する
const URL = 'http://localhost:3000/fruits.json'
request.get(URL)
        .end(callbackGet)

// データを取得した時の処理
function callbackGet (err, res) {
  if(err) {
    // 取得できなかった時の処理
    return
  }
  // ここで取得した時の処理
  console.log(res.body)
}

機能を確認

  • GETメソッドを送信する際にURLパラメータを指定したい場合にはquery()メソッドを呼び出す
const params = {q: 'search',  uid: 100}
request.get(URL)
         .query(params)
         .end(callback)
  • ヘッダーに情報を与える場合にはset()メソッド
request.get(URL)
       .set('API-KEY', 'xxxxxxxx')
       .end(callback)
  • POSTメソッドを送信する場合にはget()ではなくpost()メソッドを呼び出す。この場合はsend()メソッドでパラメータを指定する。
request.protocols(URL)
       .set('Content-Type', 'application/json')
       .send( {name: 'hoge', age: 21})
       .end(callback)
  • URLパラメータを指定する場合にはquery()で行い、リクエスト本体にパラメータを指定する場合にはsend()メソッドを使う。
request.post(URL)
       .set('Content-Type', 'application/json')
       .query( {mode: 'aave', userid: 100})
       .send( {name: 'hoge', age: 21})
       .end(callback)

2021/8/17

メモ

React + Node.js

  • Reactでは親コンポーネントから子コンポーネントに何かを伝えるときは、プロパティを介して情報を伝達する。
  • 逆に子コンポーネントの変化を親コンポーネントに伝えるときは、イベントを利用する。
  • 3-3のコードが実行できなかったが、イベントの処理とか諸々を勉強した方が良さそうなのでとりあえず先に進む。

state(状態)とprops(プロパティ)について

state(状態)

コンポーネントの状態を表す書き換え可能なデータの集まり

  • 状態とは状況に応じて変化するもの
  • 状態とは書き換え可能である
  • 状態が変更されるとコンポーネントの再描画が行われる
  • 外部には非公開でコンポーネント自身が管理するべき

props(プロパティ)

外部からのコンポーネントへの窓口というべき役割

  • プロパティは読み取り専用
  • プロパティは親要素から設定されるもの
  • 初期値と型の検証を行うことができる
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/react@15/dist/react.min.js"></script>
  <script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <div id="info"></div>
  <script type="text/babel">
    // 色選択コンポーネントの定義
    class ColorBox extends React.Component {
      constructor (props) {
        super(props)
        // 状態の初期化
        this.state = {
          index: 0,
          colors: ['red', 'blue', 'green', 'yellow', 'black']
        }
      }
      // 描画
      render () {
        // stateから値を取り出す
        const colors = this.state.colors
        const index = this.state.index
        // 現在の選択色
        const cur = (index >= 0) ? colors[index] : ''
        // 各色ごとにspan要素を生成する
        const items = colors.map((c) => {
          // 選択色なら枠をつける
          let bs = '1px solid white'
          if (c == cur){
            bs = '1px solid black'
          }
          // 色ごとのスタイルを設定
          const cstyle = {
            color: c,
            border: bs
          }
          // 色をクリックした時の処理
          const clickHandler = (e) => {
            const c = e.target.style.color
            const i = this.state.colors.indexOf(c)
            // 状態を更新する
            this.setState({index: i})
            if(this.props.onColorChange){
              this.props.onColorChange({color: c})
            }
          }
          // span要素で色のタイルを返す
          return (
            <span onClick={clickHandler}
              style={cstyle}>■</span>
          )
        })
        // 描画内容を返す
        return (
          <div>{items}</div>
        )
      }
    }
    // ReactでDOMを書き換える
    const colorHandler = (e) => {
      ReactDOM.render(
        <span>{e.color}</span>,
        document.getElementById('info')
      )
    }
    const dom = <div>
      <ColorBox id='cb' onColorChange={colorHandler} />
    </div>

    ReactDOM.render(dom,
      document.getElementById('root'))
  </script>
</body>
</html>

メモ

  • mapメソッドを使うとある配列を元にして別の配列要素を生成することができる。
  • JSXは別の部分でJSXにより生成したオブジェクトやその配列を埋め込むように指定できる。