NextjsとReduxの接続をしてstoreにデータを追加してみる

NextjsとReduxの接続をしてstoreにデータを追加してみる

LINEで送る
Pocket

前回はUI部分の実装が終わったので、次はReduxの設定とデータを入れるところまでの解説です。

公式のリポジトリを参考にしていきます。

github.com/zeit/next.js/tree/master/examples/with-redux

 

まずは、Redux関連のライブラリをインストール

yarn add redux react-redux redux-devtools-extension redux-logger

 

store.jsを作成

import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import logger from 'redux-logger'

const initialState = {
    memoList: []
}

export const actionTypes = {
  CREATE: 'CREATE',
}

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.CREATE:
        let memoList = state.memoList
        memoList.push(action.data.memo)
        return { 
            ...state, 
            memoList
        }
    default:
      return state
  }
}

export const createMemo = (memo) => {
  return { 
      type: actionTypes.CREATE,
      data: {
          memo
      }
    }
}
export const deleteMemo = (index) => {
  return { type: actionTypes.DELETE, data: index }
}

export function initializeStore (initialState = initialState) {
  return createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(logger))
  )
}

メモを追加する処理を記述。redux-loggerでconsoleでチェックできるようにしておきます。

 

lib/with-redux-store.jsを作成し、下記を記述。


import React from 'react'
import { initializeStore } from '../store'

const isServer = typeof window === 'undefined'
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__'

function getOrCreateStore (initialState) {
  // Always make a new store if server, otherwise state is shared between requests
  if (isServer) {
    return initializeStore(initialState)
  }

  // Create store if unavailable on the client and set it on the window object
  if (!window[__NEXT_REDUX_STORE__]) {
    window[__NEXT_REDUX_STORE__] = initializeStore(initialState)
  }
  return window[__NEXT_REDUX_STORE__]
}

export default App => {
  return class AppWithRedux extends React.Component {
    static async getInitialProps (appContext) {
      // Get or Create the store with `undefined` as initialState
      // This allows you to set a custom default initialState
      const reduxStore = getOrCreateStore()

      // Provide the store to getInitialProps of pages
      appContext.ctx.reduxStore = reduxStore

      let appProps = {}
      if (typeof App.getInitialProps === 'function') {
        appProps = await App.getInitialProps(appContext)
      }

      return {
        ...appProps,
        initialReduxState: reduxStore.getState()
      }
    }

    constructor (props) {
      super(props)
      this.reduxStore = getOrCreateStore(props.initialReduxState)
    }

    render () {
      return <App {...this.props} reduxStore={this.reduxStore} />
    }
  }
}

Appを受け取ってstoreと接続する関数です。

pages/_app.js

import App, { Container } from 'next/app'
import React from 'react'
import withReduxStore from '../lib/with-redux-store'
import { Provider } from 'react-redux'

console.dir(withReduxStore)
class MyApp extends App {
  render () {
    const { Component, pageProps, reduxStore } = this.props
    return (
      <Container>
        <Provider store={reduxStore}>
          <Component {...pageProps} />
        </Provider>
      </Container>
    )
  }
}

export default withReduxStore(MyApp)

pages/_app.jsを作成しAppコンポーネントをオーバーライドします。

これで、Reduxの接続は完成

 

ページコンポーネントを修正

pages/new.jsをコンテナにします。

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { actions } from '../store'
import NewComponent from '../components/new'

const mapStateToProps = () => {
    return {

    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        ...bindActionCreators(actions, dispatch)
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(NewComponent)

次にコンポーネントを作成

components/new.js

const New = (props) => {
    const handleSubmit = (e) => {
        e.preventDefault()
        const target = e.target
        const title = target.title.value
        const content = target.content.value
        props.createMemo({
            title,
            content
        })
    }

    return (
      <div>
        <h1>メモ作成</h1>
          <div>
            <form onSubmit={handleSubmit}>
              <div>
                <div>
                  <label htmlFor="">タイトル</label>
                </div>
                <input type="text" name="title" placeholder="title"/>
              </div>
              <div>
                <div>
                  <label htmlFor="">本文</label>
                </div>
                <textarea name="content" placeholder="content"/>
              </div>
              <div>
                <input type="submit" value="submit"/>
              </div>
            </form>
          </div>
      </div>
    )
}

 

これでフォームに値を入れてsubmitすると

無事、memoListに追加されました。

 

本日はここまで、次回はルーティング周りの実装をしていきたいと思います。

LINEで送る
Pocket

フロントエンド開発でお困りのことはありませんか?

フロントエンドの開発支援を行っています。

・Reactの開発をお願いしたい

・コーディング作業を依頼したい

・javascriptライブラリを作って欲しい。

上記以外にも何かありましたらお気軽にお問い合わせください。

コメントを残す