React を 触ってみた (6) – コンポーネント の 再利用
今回は 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箇所です
ココのポイントとしては ループ処理 の 部分 なのですが ドット演算子 ではなく ブラケット演算子 を 使用している点です
I referred to 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名に 変数を指定したいところを [] で 囲うところです
I referred to ES2015以降のJavaScriptでObjectのkeyに変数を使う - Qiita.
https://qiita.com/kmagai/items/95481a3b9fd97e4616c9
まとめ
今回のポイントは 変数を用いて オブジェクト内の 値を 指定したり Key を 指定している所です
普段 ドット演算子 ばかり 使っているので ブラケット演算子 を 用いることで 色々なことが出来るな と 再認識 しました
今回の修正で list-categories.jsx と list-tags.jsx は 使用しなくなりましたので 削除してしまいましょう