1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Hooks時代のReactでクラスコンポーネントを倒す

Last updated at Posted at 2022-03-11

クラスコンポーネントと関数コンポーネント

Reactにはクラスコンポーネントと関数コンポーネントがあります。現在はhooksを使える関数コンポーネントで書くのが主流です。ですが、hooksのなかった大昔に書かれたアプリはクラスコンポーネントで書かれていることが多いです。

たまに古いReact(もしくはReact Native)アプリのメンテナンスのためにクラスコンポーネントを編集することがあります。そんなときに、関数コンポーネントでもってクラスコンポーネントに立ち向かうことができます。

クラスコンポーネントの例

class ClassComponentSample extends React.Component {
  constructor(props) {
    super(props)
    this.sampleFunction = this.sampleFunction.bind(this)
    this.state = {
      likeClass: false,
    }
  }

  sampleFunction() {
    console.log('hello from Class Component')
  }
  
  render() {
    return (
      <View>
        <Text>クラスコンポーネントの例</Text>
      </View>
    )
  }
}

export default ClassComponentSample

関数コンポーネントの例

export default function FunctionComponentSample(props) {
  const [iLoveFunctional, setIsILoveFunctional] = useState(true)

  const sampleFunction = () => {
    console.log('hello from Function Component')
  }

  return (
    <View>
      <Text>関数コンポーネントの例</Text>
    </View>
  )
}

propsの受け渡し

React(React Native)ではクラスコンポーネントから関数コンポーネントへ、もしくはその逆でも普通にpropsを受け渡しできます。

以下の例ではクラスコンポーネントの子として関数コンポーネントを表示しています。そしてクラスコンポーネントで定義したstate(likeClass)と関数(sampleFunction)を渡しています。

import FunctionComponentSample from './FunctionComponentSample'

class ClassComponentSample extends React.Component {
  constructor(props) {
    super(props)
    this.sampleFunction = this.sampleFunction.bind(this)
    this.state = {
      likeClass: false,
    }
  }

  sampleFunction() {
    console.log('hello from Class Component')
  }
  
  render() {
    return (
      <FunctionComponentSample
        likeClass={this.state.likeClass}
        sampleFunction={this.sampleFunction}
      />
    )
  }
}

export default ClassComponentSample
export default function FunctionComponentSample(props) {
  const { likeClass, sampleFunction } = props

  useEffect(() => {
    console.log(likeClass) // コンソールには"false"が表示される
  }, [])

  return (
    <TouchableOpacity
      onPress={() => sampleFunction()} // コンソールには'hello from Class Component'が表示される
    >
      <Text>関数コンポーネントの例</Text>
    </TouchableOpacity>
  )
}

もちろん、この逆に関数コンポーネントの子としてクラスコンポーネントを使うこともできます。そして関数コンポーネントで定義したstateや関数を渡すことも可能です。

引数も渡す

クラスコンポーネントから受け取った関数を、関数コンポーネントから引数をつけて実行することもできます。

import FunctionComponentSample from './FunctionComponentSample'

class ClassComponentSample extends React.Component {
  constructor(props) {
    super(props)
    this.sampleFunction = this.sampleFunction.bind(this)
  }

  sampleFunction(props) {
    console.log('hello from ', props)
  }
  
  render() {
    return (
      <FunctionComponentSample
        sampleFunction={this.sampleFunction}
      />
    )
  }
}
export default ClassComponentSample
export default function FunctionComponentSample(props) {
  const { sampleFunction } = props

  return (
    <TouchableOpacity
      onPress={() => sampleFunction('function component')} // コンソールには'hello from function component'が表示される
    >
      <Text>関数コンポーネントの例</Text>
    </TouchableOpacity>
  )
}

コンテキストも渡す

React HooksでuseStateuseEffectの次に(私が)よく使うuseContextを使用してコンテキストも渡してあげます。

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

export const SampleContext = createContext();

export const SampleContextProvider = (props) => {
  const [from, setFrom] = useState('function component')
  
  return (
    <SampleContext.Provider
      value={{
        from, setFrom
      }}
    >
      {props.children}
    </SampleContext.Provider>
  )
}
import FunctionComponentSample from './FunctionComponentSample'

class ClassComponentSample extends React.Component {
  constructor(props) {
    super(props)
    this.sampleFunction = this.sampleFunction.bind(this)
  }

  sampleFunction(props) {
    console.log('hello from ', props)
  }
  
  render() {
    return (
      <FunctionComponentSample
        sampleFunction={this.sampleFunction}
      />
    )
  }
}
export default ClassComponentSample
<SampleContextProvider>
  <ClassComponentSample />
</SampleContextProvider>
import { SampleContext } from './SampleContext'

export default function FunctionComponentSample(props) {
  const { from } = useContext(SampleContext)
  const { sampleFunction } = props

  return (
    <TouchableOpacity
      onPress={() => sampleFunction(from)} // コンソールには'hello from function component'が表示される
    >
      <Text>関数コンポーネントの例</Text>
    </TouchableOpacity>
  )
}

上の例では、関数コンポーネントにおいて、クラスコンポーネントをバイパスして受け取ったコンテキスト(from)をクラスコンポーネントから受け取った関数(sampleFunction)の引数として実行しています。

まとめ

可読性が最悪ですが、クラスコンポーネントを書きたくない場合に備えて覚えておきたいtipsです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?