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 : 一部
今まで
1 2 | import ListCategories from '../component-parts/list-categories' import ListTags from '../component-parts/list-tags' |
と 呼び出していたものを
1 | import ListTaxonomies from '../component-parts/list-taxonomies' |
に 変更します
1 2 3 4 5 6 7 | const drawer = ( <div> <ListCategories /> <Divider /> <ListTags /> </div> ) |
と 書いていたコード も 修正します
1 2 3 4 5 6 7 | const drawer = ( <div> <ListTaxonomies taxonomy= "categories" /> <Divider /> <ListTaxonomies taxonomy= "tags" /> </div> ) |
ココのポイントは ListTaxonomies を読み出す際 taxonomy=”hoge” として 引数を渡しているところです
これによって 今 自分が どのtaxonomyを 処理しているのかを 指定しています
/src/component-parts/list-taxonomies.jsx
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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 : 一部
1 | import { toggleDrawer, loadCategories, loadTags } from './actions' |
を
1 | import { toggleDrawer, loadTaxonomies } from './actions' |
に 修正
1 2 | handleLoadCategories: (value) => { dispatch( loadCategories(value) ) }, handleLoadTags: (value) => { dispatch( loadTags(value) ) }, |
を
1 | handleLoadTaxonomies: (value, taxonomy) => { dispatch( loadTaxonomies(value, taxonomy) ) }, |
に 修正
handleLoadTaxonomies で 受け取った taxonomy は loadTaxonomies にも そのまま 引き渡していきます
/src/redux/actions.jsx : 一部
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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, } } |
を
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | 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 のみ
01 02 03 04 05 06 07 08 09 10 11 12 13 | 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, }) |
を
1 2 3 4 5 6 | 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 は 使用しなくなりましたので 削除してしまいましょう