【Part3】はじめてのReact勉強メモ

【Part3】はじめてのReact勉強メモ:


はじめに

前回の続きです。

公式チュートリアルのComponents and Propsからやっていきます。

業務時間中にちまちま書いているんですが、なんとかモチベーションを落とさずに継続できています・・・!


やってみる


Components and Props

Vue.jsでもやるコンポーネント分割と、コンポーネント間のデータの受け渡しのあたりの話ですね。

Part1でも若干触れましたが、基本的にclassで定義するようです。babelを使わない場合はfuntionで定義してもいいそうですが、classの方が色々と都合が良いとのこと。

こんな感じで使うんですね。コンポーネントを埋め込む際は<Welcome>のように先頭を大文字にするのがお作法のようです。

class Welcome extends React.Component { 
  render() { 
    return <h1>Hello, {this.props.name}</h1>; 
  } 
} 
 
class App extends extends React.Component { 
  render() { 
    return ( 
      <div> 
        <Welcome name="Tanaka" /> 
        <Welcome name="Sato" /> 
      </div> 
    ) 
  } 
} 
 
ReactDOM.render( 
  <App/>, 
  document.getElementById('root) 
) 
他には1コンポーネントが複雑化した際の分割方法が書かれてありましたが、Vueと同じような感じですね。

また、受け渡されるpropsはreadonlyだとのことです。これもVue.jsでは親のコンポーネントの値を変更するのは推奨されていませんでしたし、一緒ですね。


State and Lifecycle

これまではReactDOM.render()によって描画を更新する方法しか知りませんでしたが、この章ではそれ以外の方法を教えてくれるそうです。

時計のコンポーネントを作るとしたら、これまでの知見だけでは

function Clock(props) { 
  return ( 
    <div> 
      <h1>Hello, world!</h1> 
      <h2>It is {props.date.toLocaleTimeString()}.</h2> 
    </div> 
  ); 
} 
 
function tick() { 
  ReactDOM.render( 
    <Clock date={new Date()} />, 
    document.getElementById('root') 
  ); 
} 
 
setInterval(tick, 1000); 
こんな感じになりますが、これだと毎回ReactDOM.render()でアプリ全体の描画を更新することになってしまいます。

本当はClockの内部で時刻を勝手に更新していくような作りにしたい・・・。

そこで、stateをコンポーネントに定義しましょう。Vueで言うところのdataですね。
stateを使うとこんな感じにかけるそうです。

DOMの定義部分ではthis.stateでコンポーネントのstate内の値を見にいって、constructor内で渡されたpropsstateに保存するような動作にしています。

Vueで言い換えるとconstructor()created()statedataのイメージですね。

class Clock extends React.Component { 
  constructor(props) { 
    super(props); 
    this.state = {date: new Date()}; 
  } 
 
  render() { 
    return ( 
      <div> 
        <h1>Hello, world!</h1> 
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2> 
      </div> 
    ); 
  } 
} 
 
ReactDOM.render( 
  <Clock />, 
  document.getElementById('root') 
); 
続いて、時刻を更新する処理を作ります。VueだとmountedsetIntervalを入れてbeforeDestroyclearIntervalするイメージですかね。

こんな感じにかけるそうです。想像通りですね。一度constructorstateを定義すれば、クラスにプロパティを足したりするのは自由らしいです。以下の例ではtimerIDを後から追加していますね。

stateの更新はsetStateを使う必要があるそうです。。Vueだとmethodsの中にコンポーネント内関数を定義していましたが、reactだとtick()を定義しているようにクラス内に自由に定義して良さそうですね。もちろんReact.Componentの関数をオーバーライドしないように注意しなければいけ無さそうですが。

処理が呼ばれる順番はコメントに書きました。

class Clock extends React.Component { 
  // 2 
  constructor(props) { 
    super(props); 
    this.state = {date: new Date()}; 
  } 
 
  // 4 
  componentDidMount() { 
    this.timerID = setInterval( 
      () => this.tick(), 
      1000 
    ); 
  } 
 
  // 6 
  componentWillUnmount() { 
    clearInterval(this.timerID); 
  } 
 
  // 5 
  tick() { 
    this.setState({ 
      date: new Date() 
    }); 
  } 
 
  // 3 
  render() { 
    return ( 
      <div> 
        <h1>Hello, world!</h1> 
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2> 
      </div> 
    ); 
  } 
} 
 
// 1 
ReactDOM.render( 
  <Clock />, 
  document.getElementById('root') 
); 
stateを変更する際はsetState()を使う必要がありますが、statepropsは非同期で更新されるので以下のように書く必要があると。

// Wrong 
this.setState({ 
  counter: this.state.counter + this.props.increment, 
}); 
 
// Correct 
this.setState((state, props) => ({ 
  counter: state.counter + props.increment 
})); 
setStateはシャローマージ?なので、既存のプロパティを壊さず一部を置換したりできると。

こんな感じに書いても、this.setState({comments})state.postsが消えることは無いと説明しています。

constructor(props) { 
    super(props); 
    this.state = { 
      posts: [], 
      comments: [] 
    }; 
  }, 
 
  componentDidMount() { 
    fetchPosts().then(response => { 
      this.setState({ 
        posts: response.posts 
      }); 
    }); 
 
    fetchComments().then(response => { 
      this.setState({ 
        comments: response.comments 
      }); 
    }); 
  } 
残りの部分は、stateがコンポーネント内にカプセル化していて、propsは常に子コンポーネントに流れる単方向データフローであると説明しています。この辺りもVueと同じですね。


終わりに

今回はコンポーネントとライフサイクルを学びましたが、なんとなくReactでアプリを作る道筋が見えてきました。基本的な概念はVueと変わらないですし、意外とすんなり受け入れられそうですね。次回はHandling Eventsからやっていきます。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)