質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

544閲覧

再レンダリングを防ぐために子コンポーネントでconnectするべきか

mickey

総合スコア27

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/07/09 16:08

編集2020/07/09 16:31

現在、Next.jsを基盤にreact-reduxで状態管理するアプリケーションを作成しています。

以下のコードについて説明いたします。

  • Results.jsでstoreにconnectし、APIから取得済みのitemsを子コンポーネントであるListItem.jsを用いてリスト表示
  • ListItemにある保存ボタンをクリックするとコールバック関数であるhandleClickを通じてtoggleBookmarkをdispatchし、itemのプロパティーであるis_bookmarked(Boolean)を変更する

javascript

1 2// items 3 4[ 5 {id: 1, title: 'title1', is_bookmarked: true}, 6 {id: 2, title: 'title2', is_bookmarked: false} 7] 8 9// components/molecules/ListItem.js 10 11const ListItem = React.memo(({ item, handleClick }) => { 12 return ( 13 <div> 14 <p>{item.title}</p> 15 <button onClick={handleClick}> 16 {item.is_bookmarked ? '保存済み' : '保存する'} 17 </button> 18 </div> 19 ) 20}) 21 22export default ListItem 23 24// components/organisms/Results.js 25 26const Search = ({ items, toggleBookmark }} => { 27 return items.map(item => ( 28 <ListItem 29 key={item.id} 30 item={item} 31 handleClick={() => toggleBookmark(item.id)} 32 /> 33 )) 34} 35 36const mapStateToProps = (state) => ({ 37 items: state.classified.items, 38}) 39 40const mapDispatchToProps = (dispatch) => { 41 return { 42 toggleBookmark: bindActionCreators(toggleBookmark, dispatch) 43 } 44} 45 46export default connect(mapStateToProps, mapDispatchToProps)(Results) 47 48// reducer.js 49 50export default function reducer(state = [], action) { 51 switch (action.type) { 52 case actionTypes.TOGGLE_BOOKMARK: 53 return { 54 ...state, 55 items: state.items.map(el => el.id === action.payload ? { ...el, is_bookmarked: !el.is_bookmarked } : el) 56 } 57 default: 58 return state 59 } 60}

上記は可能な限りAtomic designに沿って作成したため、molecules内にあるListItemではロジックを記述せず、上層のorganismsにあるResultsにてconnect、またロジックの記述をしています。(説明のためatomsをmoleculesにまとめて記載、またcontainerとpresentationalに分けずまとめて記載しています)

この状態でreact devtoolsにあるHighlight Updateをチェックし、任意のListItemの保存ボタンをクリックすると、クリックされたボタンのあるコンポーネントだけでなく、それ以外の全てのListItemが再レンダリングされるのが確認できます。

ここで質問です。
0. クリックされたボタンのあるコンポーネントのみを再レンダリングしたい場合、どのような方法をとるべきなのでしょうか?
0. 上記の実装において問題点はありますか?

例えばResultsではなくListItemでconnectした場合は、当然ですがボタン押下時に対象のコンポーネントのみが再レンダリングされました。しかしAtomic Designの観点等からconnectするのはorganisms以上のコンポーネントでするべきだと認識しているので、それは避けたいです。

親コンポーネントでconnectし、そこからstateやコールバック関数を子コンポーネントに渡す限り、上記コードにおける親に付随する全子コンポーネントの再レンダリングは免れないのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

クリックされたボタンのあるコンポーネントのみを再レンダリングしたい場合、どのような方法をとるべきなのでしょうか?

toggleBookmark自体を<ListItem>に渡してしまえば、関数の再生成という問題はありません。

投稿2020/07/09 21:55

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mickey

2020/07/10 01:23

ご回答ありがとうございます。 <ListItem key={item.id} item={item} toggleBookmark={toggleBookmark} />として ListItemの方で、受け取ったtoggleBookmarkを使ってonClick={() => toggleBookmark(item.id)}するという理解で合っていますか? こちらが合っていると仮定して試してみたのですがクリックされたコンポーネント以外も再レンダリングされました。なので私が回答を理解できていないと思いますので、もう少しだけ詳しくご教授願えますでしょうか?
maisumakun

2020/07/10 01:27

toggleBookmark自体が変化し続けている、ということはありませんか? (なお、onClick={() => toggleBookmark(item.id)}のようにJSX内に直接関数を書くと、毎回別インスタンスとなって再描画が必ず発生します)
mickey

2020/07/10 01:44

toggleBookmarkは export const toggleBookmark = (id) => async dispatch => { return dispatch({ type: classifiedActionTypes.TOGGLE_BOOKMARK, payload: id }) } タイプとitemのidを返す関数なのですが、こちらは変化し続けると捉えるべきでしょうか?
hoshi-takanori

2020/07/11 13:20

横から失礼します。Search に渡る (そしてそのまま ListItem に渡す) toggleBookmark は、生の toggleBookmark ではなく、mapDispatchToProps の中で bindActionCreators されたものです。で、mapDispatchToProps の結果は connect の中でメモ化されるので、Search に渡る toggleBookmark は基本的に (dispatch が変わらない限り) 変化しないはずです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問