Gatsby プロジェクトに Redux サポートを追加

  1. 依存関係のインストール:

npm install redux 反応-redux

  1. src/store ディレクトリを作成し、createStore.js ファイルを作成します。

createStore.js ファイルを作成し、createStore メソッドをエクスポートします。

import { combineReducers } from 'redux'
import userReducer from './user.reducer'

export default combineReducers(userReducer)

  1. ストア ディレクトリにリデューサーを保存するためのリデューサー フォルダーを作成します。

src/store/reducers/user.reducer.js

export const InitialState = {
  email: '[email protected]',
  name: 'huiquan',
  avatar: 'https://api.realworld.io/images/demo-avatar.png',
  loginStatus: 0
}

export default (state = InitialState, action) => {
  switch (action.type) {
    case 'modify-email':
      return { ...state, email: action.payload }
    case 'modify-name':
      return { ...state, name: action.payload }
    case 'modify-login-status':
      return { ...state, loginStatus: action.payload }
    case 'login':
      return { ...state, ...action.payload, loginStatus: 1 }
    default:
      return state
  }
}

  1. rootReducer.jsを作成する

src/store/reducers/root.reducer.js combinReducers メソッドを使用して、reducers ディレクトリ内のレデューサーをマージしてエクスポートします。

import { combineReducers } from 'redux'
import userReducer from './user.reducer'

export default combineReducers({ userReducer })

  1. クライアントのプロバイダーを構成し、ルート ディレクトリに gatsby-browser.js ファイルを作成し、wrapRootElement メソッドをエクスポートします。

const React = require('react')
const Layout = require('./src/components/Layout').default

const { Provider } = require('react-redux')

const createStore = require('./src/store/createStore').default

module.exports = {
  wrapPageElement: ({ element }) => {
    return <Layout>{element}</Layout>
  },
  wrapRootElement: ({ element }) => {
    return <Provider store={createStore()}>{element}</Provider>
  }
}

  1. サーバー側でプロバイダーを構成し、ルート ディレクトリに gatsby-ssr.js ファイルを作成します。

const React = require('react')
const { Provider } = require('react-redux')
const createStore = require('./src/store/createStore').default

module.exports = {
  wrapRootElement: ({ element }) => {
    return <Provider store={createStore()}>{element}</Provider>
  }
}

  1. ストア内のデータを使用し、ページまたはコンポーネント内のデータを変更します

useDispatch、useSelector フック関数をコンポーネントに導入し、それらを使用してストア内の状態を変更します。

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'

export default function Header () {
  const userReducer = useSelector(state => state.userReducer)
  const dispatch = useDispatch()

  return (
    <nav className='navbar navbar-light'>
      <div className='container'>
        <a className='navbar-brand' href='index.html'>
          conduit
        </a>
        <ul className='nav navbar-nav pull-xs-right'>
          <li className='nav-item'>
            {/* Add "active" class when you're on that page" */}
            <a className='nav-link active'>Home</a>
          </li>
          {userReducer.loginStatus === 1 && (
            <li className='nav-item'>
              <a className='nav-link'>
                {' '}
                <i className='ion-compose' />
                &nbsp;New Article{' '}
              </a>
            </li>
          )}
          <li className='nav-item'>
            <a className='nav-link'>
              {' '}
              <i className='ion-gear-a' />
              &nbsp;Settings{' '}
            </a>
          </li>
          {userReducer.loginStatus === 0 && (
            <>
              <li className='nav-item'>
                <a
                  onClick={() => dispatch({ type: 'login' })}
                  className='nav-link'
                >
                  Sign in
                </a>
              </li>
              <li className='nav-item'>
                <a className='nav-link'>Sign up</a>
              </li>
            </>
          )}
          {userReducer.loginStatus === 1 && (
            <li className='nav-item'>
              <a
                className='nav-link ng-binding'
                ui-sref-active='active'
                ui-sref='app.profile.main({ username: $ctrl.currentUser.username })'
              >
                <img className='user-pic' src={userReducer.avatar} />
                {userReducer.name}
              </a>
            </li>
          )}
        </ul>
      </div>
    </nav>
  )
}

  1. redux の非同期処理サポート、redux-saga を追加

npm インストール redux-saga

src/store/sagas フォルダーを作成し、src/store/sagas/user.saga.js および src/store/sagas/root.saga.js を作成します。

// src/store/sagas/user.saga.js
import axios from 'axios'
import { takeEvery, put, delay } from 'redux-saga/effects'

function* login_async (action) {
  console.log(action.payload)
  const { data } = yield axios.post(
    'https://api.realworld.io/api/users/login',
    {
      user: action.payload.user
    }
  )
  yield put({ type: 'login', payload: data.user })
}
export default function* userSaga () {
  yield takeEvery('login_async', login_async)
}
// src/store/sagas/root.saga.js
import { all } from 'redux-saga/effects'
import userSaga from './user.saga'

export default function* rootSga () {
  yield all([userSaga()])
}

ページコンポーネントでは以下を使用します。

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'

export default function Header () {
  const userReducer = useSelector(state => state.userReducer)
  const dispatch = useDispatch()

  return (
    <nav className='navbar navbar-light'>
      <div className='container'>
        <a className='navbar-brand' href='index.html'>
          conduit
        </a>
        <ul className='nav navbar-nav pull-xs-right'>
          <li className='nav-item'>
            {/* Add "active" class when you're on that page" */}
            <a className='nav-link active'>Home</a>
          </li>
          {userReducer.loginStatus === 1 && (
            <li className='nav-item'>
              <a className='nav-link'>
                {' '}
                <i className='ion-compose' />
                &nbsp;New Article{' '}
              </a>
            </li>
          )}
          <li className='nav-item'>
            <a className='nav-link'>
              {' '}
              <i className='ion-gear-a' />
              &nbsp;Settings{' '}
            </a>
          </li>
          {userReducer.loginStatus === 0 && (
            <>
              <li className='nav-item'>
                <a
                  onClick={() => dispatch({ type: 'login' })}
                  className='nav-link'
                >
                  Sign in
                </a>
              </li>
              <li className='nav-item'>
                <a
                  onClick={() =>
                    dispatch({
                      type: 'login_async',
                      payload: {
                        user: {
                          email: '[email protected]',
                          password: '111111'
                        }
                      }
                    })
                  }
                  className='nav-link'
                >
                  Sign up
                </a>
              </li>
            </>
          )}
          {userReducer.loginStatus === 1 && (
            <li className='nav-item'>
              <a
                className='nav-link ng-binding'
                ui-sref-active='active'
                ui-sref='app.profile.main({ username: $ctrl.currentUser.username })'
              >
                <img className='user-pic' src={userReducer.image} />
                {userReducer.username}
              </a>
            </li>
          )}
        </ul>
      </div>
    </nav>
  )
}

おすすめ

転載: blog.csdn.net/u011024243/article/details/129650609