GatsbyJs + Redux Toolkit Saga + React Bootstrap + Storybook

GatsbyJs + Redux Toolkit Saga + React Bootstrap + Storybook I. Tạo và cài đặt các thư viện cần thiết 1. Init Gatsbyjsnpm init gatsby Bây giờ mình chạy thử cd name-project/ npm run develop Ứng dụng gatsby của bạn sẽ chạy trên cổng 8000 http://localhost:8000/ 2. Thêm storybook npx sb init npm install -D

GatsbyJs + Redux Toolkit Saga + React Bootstrap + Storybook

I. Tạo và cài đặt các thư viện cần thiết

1. Init Gatsbyjsnpm init gatsby

Bây giờ mình chạy thử

cd name-project/
npm run develop

Ứng dụng gatsby của bạn sẽ chạy trên cổng 8000
http://localhost:8000/

2. Thêm storybook

npx sb init
npm install -D dotenv-webpack
npm install -D html-webpack-plugin

npm run storybook

Ứng dụng của bạn sẽ chạy trên
http://localhost:6006/?path=/story/example-introduction--page

3. Thêm React Bootstrapnpm install [email protected][email protected]

4. Thêm Redux toolkit Saganpm install @reduxjs/toolkit react-redux redux-saga

II. Config store

  1. Bạn phải tạo file gatsby-browser.js vào trong dự án
import React from 'react';
import { Provider } from 'react-redux';
import store from './src/store/index';
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'

export const wrapRootElement = ({ element }) => {
  return <Provider store={store}>{element}</Provider>;
};

Tạo file gatsby-ssr.js

import React from 'react';
import { Provider } from 'react-redux';
import store from './src/store/index';

export const wrapRootElement = ({ element }) => {
  return <Provider store={store}>{element}</Provider>;
};

Tạo thêm file gatsby-node.js để có thể link đến thư mục của bạn khi SSR

const path = require('path');

exports.onCreateWebpackConfig = ({ actions }) => {
  actions.setWebpackConfig({
    resolve: {
      modules: [path.resolve(__dirname, 'src'), 'node_modules']
    }
  });
};

  1. Bạn cần tạo thư mục store

Cấu trúc sẽ tùy vào dự án của bạn. Trong ví dụ này mình sẽ cấu trúc store theo từng feature.
Nội dung các file trong store sẽ như sau
store/index.js

import { configureStore, Action, getDefaultMiddleware } from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';

import rootReducers from './reducers';
import rootSaga from './sagas';

const sagaMiddleware = createSagaMiddleware();
const middleware = [...getDefaultMiddleware({ thunk: false }), sagaMiddleware];
const store = configureStore({
  reducer: rootReducers,
  middleware,
});

sagaMiddleware.run(rootSaga);
export default store

store/reducers.js

import { combineReducers } from "redux";
import count from "./features/count";

export default combineReducers({
  count,
});

store/features/count.js

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  count: 0,
};

// Slice
const countSlice = createSlice({
  name: "count",
  initialState,
  reducers: {
    setCount: (state, action) => {
      const { payload } = action;
      state.count = payload;
    },
  },
});

// Selectors
export const countSelector = (state) => state.count;

// Actions
export const { setCount } = countSlice.actions;

// Reducers
export default countSlice.reducer;

store/sagas/index.js

import { takeEvery } from 'redux-saga/effects';
import { sagaActions } from './typeSagas';
import { increaseCount } from './count';

export default function* rootSaga() {
  yield takeEvery(sagaActions.INCREASE, increaseCount);
}

store/sagas/count.js

import { put } from "redux-saga/effects";
import { setCount } from "../features/count";

export function* increaseCount(payload) {
  try {
    let result = payload.count + 1;
    yield put(setCount(result));
  } catch (e) {
    console.log(e);
  }
}

store/sagas/typeSagas.js

export const sagaActions = {
  INCREASE: 'INCREASE'
};

Done config cho store.
Các bạn kiểm tra với chrome devtool thì sẽ thấy store đã được khởi tạo.

Ok giờ thì sẽ sửa lại file pages/index.js nhé

import * as React from "react";
import { Badge, Button } from "react-bootstrap";
import { useSelector, useDispatch } from "react-redux";
import { countSelector } from "store/features/count";
import { sagaActions } from "../store/sagas/typeSagas";

const pageStyles = {
  color: "#232129",
  padding: 96,
  fontFamily: "-apple-system, Roboto, sans-serif, serif",
};
const headingStyles = {
  marginTop: 0,
  marginBottom: 64,
  maxWidth: "100%",
};
const headingAccentStyles = {
  color: "#663399",
};

const IndexPage = () => {
  const { count } = useSelector(countSelector);
  const dispatch = useDispatch();
  return (
    <main style={pageStyles}>
      <title>Home Page</title>
      <h1 style={headingStyles}>
        Congratulations
        <br />
        <span style={headingAccentStyles}>— you just made a Gatsby site! </span>
        <Badge bg="success">{count}</Badge>
        <span role="img" aria-label="Party popper emojis">
          🎉🎉🎉
        </span>
      </h1>
      <Button onClick={() => dispatch({ type: sagaActions.INCREASE, count })}>
        INCREASE
      </Button>
    </main>
  );
};

export default IndexPage;

Kết quả sẽ là thế này nhé

Bước cuối cùng chúng ta sẽ đi tích hợp store cho storybook nhé
Trong file storybook/preview.js các bạn cần tạo store cho storebook

import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from '../src/store/reducers'


export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

// config store for storybook
const storeInit = createStore(reducer)
export const decorators = [
  (Story) => (
    <Provider store={storeInit}>
      <Story />
    </Provider>
  ),
]

Có vẻ hơi dài nên sử dụng Storybook và cấu hình các bạn vào xem trong source nhé
Link source demo
https://github.com/vinctuyen/Gatsby-Redux-toolkit-Redux-saga-Storybook
Thanks for reading.

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ