孤独プログラマー譚

孤独死が近い。

React Redux

Vue.jsのVuexと似てるけど、こんなんだったっけな。

import React from 'react';
import QuxComponent from '../QuxComponent/QuxComponent';
import { createStore } from 'redux';
import { Provider } from 'react-redux';

const BazComponent = () => {
  const initial_state = {
    a: 1,
    b: 2,
    c: 3,
  }

  const reducer = (state = initial_state, action) => {
    switch (action.type) {
      case 'increment':
        return {
          ...state,
          a: state.a + 1,
          b: state.b * 2,
        }
      default:
        return state
    }
  }
  const store = createStore(reducer)

  return (
    <div className="App">
      BazComponent<br/>
      <Provider store={store}>
        <QuxComponent/>
      </Provider>
    </div>
  )
};

export default BazComponent;
import React, { Component } from 'react';
import { connect } from 'react-redux';

class QuxComponent extends Component {
  constructor (props) {
    super(props)
    this.doAction = this.doAction.bind(this)
  }

  doAction () {
    this.props.dispatch({ type: 'increment' })
  }

  render () {
    return (
      <div className="App">
        QuxComponent Component
        <div>{this.props.a}</div>
        <div>{this.props.b}</div>
        <div>{this.props.c}</div>
        <button onClick={this.doAction}>increment</button>
      </div>
    )
  }
}

QuxComponent = connect(state => state)(QuxComponent)

export default QuxComponent;

React hooks useContext 切り出し

切り出されたコンテキスト。

import React, { useState, createContext } from 'react';

export const QuxContext = createContext()

export function QuxContextProvider(props) {
  const [value, setValue] = useState(0)

  return (
    <QuxContext.Provider value={[value, setValue]}>
      {props.children}
    </QuxContext.Provider>
  )
}


親、子、孫コンポーネント

import React from 'react';
import BarComponent from '../BarComponent/BarComponent';
import { QuxContextProvider } from '../../QuxContext';

const FooComponent = () => {
  return (
    <div className="App">
      FooComponent
      <QuxContextProvider>
        <BarComponent/>
      </QuxContextProvider>
    </div>
  )
};

export default FooComponent;
import React, { useContext, useState } from 'react';
import BazComponent from '../BazComponent/BazComponent';
import { QuxContext } from '../../QuxContext';

const BarComponent = () => {
  const [value, setValue] = useContext(QuxContext)

  return (
    <div className="App">
      BarComponent
      <div><button onClick={() => setValue(value + 1)}>increment</button></div>
      <div>{value}</div>
      <BazComponent />
    </div>
  )
};

export default BarComponent;
import React, { useContext, useState } from 'react';
import { QuxContext } from '../../QuxContext';

const BazComponent = () => {
  const [value, setValue] = useContext(QuxContext)

  return (
    <div className="App">
      BazComponent<br/>
      <div><button onClick={() => setValue(value + 1)}>increment</button></div>
      <div>{value}</div>
    </div>
  )
};

export default BazComponent;

React hooks useContext

え、useContextがあったらReduxいらないってこと…?

import React, { useState, useEffect } from 'react';
import BarComponent from '../BarComponent/BarComponent';

export const UserCount = React.createContext()

const FooComponent = () => {
  const [count, setCount] = useState(0)

  return (
    <div className="App">
      FooComponent Component<br />
      <button onClick={() => setCount(count + 1)}>increment</button>
      <UserCount.Provider value={[count, setCount]}>
      <BarComponent />
      </UserCount.Provider>
    </div>
  )
};

export default FooComponent;
import React from 'react';
import BazComponent from '../BazComponent/BazComponent';

const BarComponent = () => (
  <div className="App">
    BarComponent Component
    <BazComponent />
  </div>
);

export default BarComponent;
import React, {useContext} from 'react';
import { UserCount } from '../FooComponent/FooComponent';

const BazComponent = () => {
  const [count, setCount] = useContext(UserCount)

  return (
    <div className="App">
      BazComponent Component<br />
      <button onClick={() => setCount(count + 1)}>increment</button>
      <div>{count}</div>
    </div>
  )
};

export default BazComponent;

React hooks useEffect

え、useEffect便利すぎへん?
Vue.js3未満にそういう機能ないように思うけど…。
Vue.js3(Vue-next)が出るまで、完全にReactがリードしてるような…。


increment1のボタンをクリックした時のみ、コンソールが出力される。

import React, { useState, useEffect } from 'react';

const FooComponent = () => {
  const [count1, setCount1] = useState(0)
  const plusOne1 = () => setCount1(count1 + 1)

  const [count2, setCount2] = useState(0)
  const plusOne2 = () => setCount2(count2 + 1)

  useEffect(() => {
    console.log(123)
  }, [count1]);

  return (
    <div className="App">
      <div>
        <button onClick={plusOne1}>increment1</button>
      </div>
      <div>{count1}</div>

      <div>
        <button onClick={plusOne2}>increment2</button>
      </div>
      <div>{count2}</div>
    </div>
  )
};

export default FooComponent;

React hooks 全て選択チェックボックス

import React, { useState } from 'react';

const FooComponent = () => {
  const [a, setA] = useState(true)
  const [b, setB] = useState(true)
  const [c, setC] = useState(true)

  const selectAll = (e) => {
    let bool = e.target.checked ? true : false
    setA(bool)
    setB(bool)
    setC(bool)
  }

  return (
    <div className="App">
      <div>
        A<input type="checkbox" checked={a} onChange={() => setA(!a)} />
        B<input type="checkbox" checked={b} onChange={() => setB(!b)} />
        C<input type="checkbox" checked={c} onChange={() => setC(!c)} />
      </div>
      <div>
        All<input type="checkbox" onChange={selectAll} checked={a && b && c}/>
      </div>
    </div>
  )
};

export default FooComponent;

React hooks useState

Reactのクラスコンポーネントを触ってみたが、双方向データバインディングのあるVue.jsに比べて使いにくすぎて驚いた。
ただ、Hooksは使いやすい。これなら、Reactでも普通に使っていけそう。

import React, { useState } from 'react';

const FooComponent = () => {
  const [count, setCount] = useState(0)

  const double = () => setCount(count * 2)

  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>increment</button><br />
      <button onClick={double}>double</button>
      <div>{count}</div>
    </div>
  )
};

export default FooComponent;

Angular FormArray

配列で動的にフォーム生成したい時は、FormArrayを使う。

farray = this.fb.array([
  true,
  false,
  true,
])
<input type="checkbox" [formControl]="farray.at(0)">
<input type="checkbox" [formControl]="farray.at(1)">
<input type="checkbox" [formControl]="farray.at(2)">
<div>a: {{farray.at(0).value}}</div>
<div>b: {{farray.at(1).value}}</div>
<div>c: {{farray.at(2).value}}</div>