てくてくあるく

WordPress の テーマ とか プラグイン に ついて 勉強しています

今回は list-categories.jsx と list-tags.jsx を まとめて 1つにします

前回の記事

React を 触ってみた (5) – 非同期処理 と Router
https://tekuaru.jack-russell.jp/2018/05/02/1767/

ListTaxonomies として 1つにまとめる


list-categories.jsx と list-tags.jsx の ソース を よく見ると コードはだいたい同じ

でも 細部が違う… だから 別々に処理… なんて 事を していました

みなさんも 経験があるかと おもいます

今回は そんなよくある失敗(??) を 解消していきます


/src/component/main.jsx : 一部


今まで

import ListCategories from '../component-parts/list-categories'
import ListTags from '../component-parts/list-tags'

と 呼び出していたものを

import ListTaxonomies from '../component-parts/list-taxonomies'

に 変更します


const drawer = (
  <div>
    <ListCategories />
    <Divider />
    <ListTags />
  </div>
)

と 書いていたコード も 修正します

const drawer = (
  <div>
    <ListTaxonomies taxonomy="categories" />
    <Divider />
    <ListTaxonomies taxonomy="tags" />
  </div>
)

ココのポイントは ListTaxonomies を読み出す際 taxonomy=”hoge” として 引数を渡しているところです

これによって 今 自分が どのtaxonomyを 処理しているのかを 指定しています


/src/component-parts/list-taxonomies.jsx


import React from 'react'

import { Link } from 'react-router-dom'

import PropTypes from 'prop-types'

import { withStyles } from 'material-ui/styles'

import List, { ListSubheader, ListItem, ListItemText } from 'material-ui/List'

import { connect } from 'react-redux'

import { mapStateToProps, mapDispatchToProps } from '../redux/containers'

const styles = theme => ({
  drawerListSubheader: {
    backgroundColor: theme.palette.background.paper,
  },
})

class ListTaxonomies extends React.Component {
  constructor (props) {
    super(props)
  }

  componentWillMount() {
    var taxonomiesURL = this.props.API.default + this.props.API.namespace + this.props.taxonomy + '/' + '?' + 'per_page=100'
    this.props.handleLoadTaxonomies(taxonomiesURL, this.props.taxonomy)
  }

  render(){
    const { classes } = this.props

    return(
      <div>
        <List>
          <ListSubheader className={classes.drawerListSubheader} component="div">{this.props.taxonomy}</ListSubheader>
          {this.props[this.props.taxonomy].map((item) => {
            return (
              <ListItem button key={item.id} component={Link} to={`/${this.props.taxonomy}/${item.id}/`}>
                <ListItemText primary={item.name} />
              </ListItem>
            )
          })}
        </List>
      </div>
    )
  }
}

ListTaxonomies.propTypes = {
  classes: PropTypes.object.isRequired,
  theme: PropTypes.object.isRequired,
}

export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles, { withTheme: true })(ListTaxonomies))

ここも 今までの list-categories.jsx や list-tags.jsx と 同じですが main.jsx で 指定した taxonomy の 値を 使用しているところがあります

  • componentWillMount の URL生成時
  • componentWillMount の handleLoadTaxonomies への 引数
  • ListSubheader の 表示テキスト
  • ListSubheader 後の ループ処理
  • ListItem の Link to の 値

の 5箇所です

ココのポイントとしては ループ処理 の 部分 なのですが ドット演算子 ではなく ブラケット演算子 を 使用している点です

JavaScriptのオブジェクトのキーに変数の値を使うTips - Qiitaを参考にさせていただきました。
https://qiita.com/masarufuruya/items/d29a567d0ca4bbfb00cb

Redux の 処理修正


何回か 同じことを やらされてきたので そろそろ 感覚的に わかってきたかと思いますが containers.jsx actions.jsx reducers.jsx 達を 修正していきます


/src/redux/containers.jsx : 一部


import { toggleDrawer, loadCategories, loadTags } from './actions'

import { toggleDrawer, loadTaxonomies } from './actions'

に 修正


handleLoadCategories: (value) => { dispatch( loadCategories(value) ) },
handleLoadTags: (value) => { dispatch( loadTags(value) ) },

handleLoadTaxonomies: (value, taxonomy) => { dispatch( loadTaxonomies(value, taxonomy) ) },

に 修正

handleLoadTaxonomies で 受け取った taxonomy は loadTaxonomies にも そのまま 引き渡していきます


/src/redux/actions.jsx : 一部


export function loadCategories( value ) {
  return function(dispatch) {
    fetch(value)
      .then(response => response.json())
      .then(result => dispatch(setCategories(result)))
      .catch(error => console.log(error))
    // end fetch
  }
}

export function setCategories( value ) {
  return {
    type: 'SET-CATEGORIES',
    value,
  }
}

export function loadTags( value ) {
  return function(dispatch) {
    fetch(value)
      .then(response => response.json())
      .then(result => dispatch(setTags(result)))
      .catch(error => console.log(error))
    // end fetch
  }
}

export function setTags( value ) {
  return {
    type: 'SET-TAGS',
    value,
  }
}

export function loadTaxonomies( value, taxonomy ) {
  return function(dispatch) {
    fetch(value)
      .then(response => response.json())
      .then(result => dispatch(setTaxonomies(result, taxonomy)))
      .catch(error => console.log(error))
    // end fetch
  }
}

export function setTaxonomies( value, taxonomy ) {
  return {
    type: 'SET-TAXONOMIES',
    value,
    taxonomy,
  }
}

に 修正

こちらも loadTaxonomies で 受け取った taxonomy を setTaxonomies に 引き渡して さらに 戻り値として 渡しています


/src/redux/reducers.jsx : case のみ


case 'SET-CATEGORIES':
  console.log( 'categories :' )
  console.log( action.value )
  return Object.assign({}, state, {
    categories: action.value,
  })

case 'SET-TAGS':
  console.log( 'tags :' )
  console.log( action.value )
  return Object.assign({}, state, {
    tags: action.value,
  })

case 'SET-TAXONOMIES':
  console.log( action.taxonomy + ' :' )
  console.log( action.value )
  return Object.assign({}, state, {
    [action.taxonomy]: action.value,
  })

に 修正

ココでのポイントは Key名に 変数を指定したいところを [] で 囲うところです

ES2015以降のJavaScriptでObjectのkeyに変数を使う - Qiitaを参考にさせていただきました。
https://qiita.com/kmagai/items/95481a3b9fd97e4616c9

まとめ


今回のポイントは 変数を用いて オブジェクト内の 値を 指定したり Key を 指定している所です

普段 ドット演算子 ばかり 使っているので ブラケット演算子 を 用いることで 色々なことが出来るな と 再認識 しました

今回の修正で list-categories.jsx と list-tags.jsx は 使用しなくなりましたので 削除してしまいましょう

Related Article

React を 触ってみた (1) – 開発環境

詳細へ »

React を 触ってみた (3) – Material-UI

詳細へ »