LoginSignup
0
0

More than 3 years have passed since last update.

脳内メモリ使わず初期設定(create-react-app)その1

Last updated at Posted at 2020-03-05

その2(stylus実験…動かない)
https://qiita.com/DaisukeNishi/items/57cb3a440ddfb876ee9a
その3
https://qiita.com/DaisukeNishi/items/78bdb0ec6af9aea204d2

※自分用boilerPlate作ればいいじゃんgit clone一発だよと思うじゃないですか。
一応、写経も兼ねて反芻してるです。

「感謝の正拳突き1日1万回」...じゃないですが、
毎日環境構築を反芻してたら型として覚えられると思った。
変な型が身についてしまったらゴメンなさい。
image.png

(↓グローバルインストールは初回のみ)

npm i -g create-react-app
sudo npm install eslint -g
sudo npm i -g eslint-plugin-react

プロジェクト(名前例)react_1231を作る。

create-react-app react_`date '+%m%d'`
cd react_`date '+%m%d'`

git初期化

git init
open .gitignore

セーブポイントは除外。

.history

リモートを作っておく。

open https://github.com/
open https://bitbucket.org/

プッシュする。

git remote add origin (GitのURL)
git push -u origin master

設定オーバーライドの鉄板。

yarn add react-app-rewired customize-cra
touch config-overrides.js
open config-overrides.js
config-overrides.js
const { override,useBabelRc,useEslintRc,disableEsLint} = require("customize-cra");
module.exports = override(
  useBabelRc(".babelrc.json"),
  useEslintRc(".eslintrc.json"),
  //disableEsLint()
);

NPMスクリプトを書き換える。

open package.json
package.json
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },

CSSのプラグインを入れる

yarn add styled-jsx
yarn add styled-jsx-plugin-sass
//yarn add styled-jsx-plugin-stylus //(未検証)
yarn add node-sass
//yarn add stylus stylus-loader

設定ファイルを作る

touch .babelrc.json
open .babelrc.json
babelrc.json
{
  "presets": [
    "react-app"
  ],
  "plugins": [
    ["styled-jsx/babel",
      { "plugins": ["styled-jsx-plugin-sass"] }
      //{ "plugins": ["styled-jsx-plugin-stylus"] } //どっちか選ぶ
    ]
  ]
}
eslint --init

>To check syntax and find problems
>JavaScript modules (import/export) 
>React
Typescript? N
Where code run?
◎ Browser
◎ Node
What format?
>JSON
eslint@latest install? Y

yarn startしたらつけっぱなし。終了はCtrl+C

yarn start

エラーなければ、テンプレートを編集する。

サンプルの「App.js」を編集する

open App.js
src/App.js
import React, { Fragment } from 'react';
import logo from './logo.svg';
function App() {
  return (
    <Fragment>
      //HTML
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
      //CSS
      <style jsx>{`
        .App {
          text-align: center;
        }
        .App-logo {
          height: 40vmin;
          pointer-events: none;
        }
        @media (prefers-reduced-motion: no-preference) {
          .App-logo {
            animation: App-logo-spin infinite 20s linear;
          }
        }
        .App-header {
          background-color: #282c34;
          min-height: 100vh;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          font-size: calc(10px + 2vmin);
          color: white;
        }
        .App-link {
          color: #61dafb;
        }
        @keyframes App-logo-spin {
          from {
            transform: rotate(0deg);
          }
          to {
            transform: rotate(360deg);
          }
        }
      `}</style>
    </Fragment>
  );
}
export default App;

子コンポーネントのテンプレを作る

touch Template.js
src/Template.js
import React from 'react'
import { connect } from 'react-redux'

const render = () => {
  return (
  <Fragment>
    <div className="">

    </div>
    <style jsx>{`

    `}</style>
  </Fragment>
  )
}

const mapState = (state) =>{
  return {

  }
}

const mapDispatch = (dispatch) => {
  return {

  }
}

export default connect(mapState, mapDispatch)(render)

ディレクトリの構造をやや過剰に作る。

mkdir -p src/components/common/common src/components/common/home src/components/common/list src/components/common/detail src/components/pc/common src/components/pc/home src/components/pc/list src/components/pc/detail src/components/sp/common src/components/sp/home src/components/sp/list src/components/sp/detail src/assets/img src/scss src/views src/components/pc/notfound src/components/sp/notfound src/components/pc/about src/components/sp/about src/components/pc/company src/components/sp/company src/components/pc/policy src/components/sp/policy src/components/pc/terms src/components/sp/terms src/components/pc/contact src/components/sp/contact

ディレクトリにTemplate.jsを埋めていく。

cd src
rm App.css
find . -name "*" -type d -exec cp Template.js {} \;

不要なやつは消す。

rm Template.js scss/Template.js assets/Template.js assets/img/Template.js components/Template.js 
 components/common/Template.js components/pc/Template.js components/sp/Template.js
cd  ../

reduxに必要となるプラグインを入れる

yarn add axios immer react-app-polyfill react-router-dom react-transition-group react-redux redux redux-devtools redux-thunk

IE対応あるだろうからpolyfillautoprefixerは忘れずに

package.json
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not ie <= 11", //←コレ追記
      "not op_mini all"
    ],

reduxで必要なstoreを作る

mkdir src/store
touch src/store/index.js src/store/actions.js src/store/reducer.js
open src/store/index.js
src/store/index.js
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from './reducer'
import * as actions from './actions'
import thunk from 'redux-thunk'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(thunk))
)
export default store
export { reducer, actions }
open src/store/actions.js
src/store/actions.js
import axios from 'axios'

export const showSide = () => ({
  type: 'showSide'
})

export const hideSide = () => ({
  type: 'hideSide'
})

export const changeL = () => ({
  type: 'changeL'
})

export const showLR = (val) =>({
  type: 'showLR',
  val
})
open src/store/reducer.js
src/store/reducer.js
import produce from "immer"
import { combineReducers } from 'redux'

const defaultState = {
  sideBar: false,
  blurStyle: {},
  cover: false
}

const mutations = {
  showSide (state, action) {
    return produce(state, (state) => {
      state.sideBar = true
      state.cover = true
      state.blurStyle = {transform: 'translateX(15rem)', filter: 'blur(3px)'}
    })
  },
  hideSide (state, action) {
    return produce(state, (state) => {
      if (state.LR) {
        state.LR = false
      } else {
        state.sideBar = false
      }
      state.cover = false
      state.blurStyle = {}
    })
  }
}

const store = (state = defaultState, action) => {
  if (mutations[action.type]) {
    return mutations[action.type](state, action)
  }
  return state
}

export default combineReducers({
  store
})
open src/index.js

src/index.jsを書き換える。serviceworker.js下に追記する、exportは書き換える

src/index.js
//(省略)
import store from './store'
import { Provider } from 'react-redux'

ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'))

ブラウザ表示にエラーが出てないか確認。

ヘッダ・フッター・メニューつける

touch src/components/common/common/Header.js
open src/components/common/common/Header.js
src/components/common/common/Header.js
import React, {Fragment} from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { actions } from '../../../store'

const render = (props) => {
  return (
    <Fragment>
      <div className="header">
        <span className="button" onClick={props.showSide}>
          
        </span>
        <Link to='/'>
          <span className="title">react-app</span>
        </Link>
      </div>
      <style jsx>{`
        .header{
          position: fixed;
          top: 0;
          right: 0;
          left: 0;
          z-index: 5;
          background-color: #fff;
          box-shadow: 0 3px 15px 0px #0001;
          vertical-align: middle;
          color: #02b3e4;

          .button{
            height: 4rem;
            line-height: 4rem;
            display: inline-block;
            padding: 0 1rem;
            text-align: center;
            font-weight: 800;
            font-size: 1.2rem;
          }

          .title{
            font-size: 1.4rem;
            font-weight: bold;
            margin-left: 1.5%;
            height: 3rem;
            line-height: 3rem;
          }
        }
      `}</style>
    </Fragment>
  )
}

const mapState = (state) =>{
  return {
  }
}

const mapDispatch = (dispatch) => {
  return {
    showSide() {
      dispatch(actions.showSide())
    }
  }
}

export default connect(mapState, mapDispatch)(render)

サイドメニューを用意。

touch src/components/common/common/Menu.js
open src/components/common/common/Menu.js
src/components/common/common/Menu.js
import React, {Fragment} from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { actions } from '../../../store'

const render = (props) => {
  return (
    <Fragment>
      <div className="bar">
        <div className="btn-wrapper">
          <Link to="/">
            <span type="button" className="btn btn-light" onClick={props.hideSide}>閉じる</span>
          </Link>
        </div>
      </div>

      <style jsx>{`
        .bar{
          position: fixed;
          top: 0;
          bottom: 0;
          left: 0;
          width: 15rem;
          background-color: #fff;
          padding-top: 2rem;
          box-shadow: 0px 2px 20px #0003;
          z-index: 6;

          .btn-wrapper{
            height: 4.5rem;
            line-height: 4.5rem;
            text-align: center;
          }
        }
      `}</style>
    </Fragment>
  )
}

const mapState = (state) =>{
  return {
  }
}

const mapDispatch = (dispatch) => {
  return {
    hideSide () {
      dispatch(actions.hideSide())
    }
  }
}

export default connect(mapState, mapDispatch)(render)

フッターを準備

touch src/components/common/common/Footer.js
open src/components/common/common/Footer.js
src/components/common/common/Footer.js
import React,{Fragment} from 'react'
import { connect } from 'react-redux'

const Footer = () => {
  return (
    <Fragment>
      <div className="footer">
        Copyright@XXX-XXX co,Ltd.
      </div>
      <style jsx>{`
        .footer{
          color: #777;
          margin-top: 0rem;
          height: 4rem;
          line-height: 4rem;
          text-align: center;
          background-color: #efefef;
        }
      `}</style>
    </Fragment>
  )
}

export default connect(null, null)(Footer)

App.jsredux対応版に書き換える

src/App.js
import React, { Fragment } from 'react';
import { connect } from 'react-redux'
import logo from './logo.svg';

import { BrowserRouter }  from 'react-router-dom'
import { actions } from './store'

import Header from './components/common/common/Header'
import Footer from './components/common/common/Footer'
import Menu from './components/common/common/Menu'

import { CSSTransition } from 'react-transition-group'

function App( props ) {

  return (
    <Fragment>
      <BrowserRouter>
        {/* HTML */}
        <div className="App">
          <Header></Header>
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
            </p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
            </a>
          </header>
          <Footer></Footer>
          <CSSTransition in={props.sideBar} timeout={300} classNames="fade" unmountOnExit>
            <Menu />
          </CSSTransition>
        </div>
        {/* CSS */}
        <style jsx>{`
          .App {
            text-align: center;
          }

          .App-logo {
            height: 40vmin;
            pointer-events: none;
          }

          @media (prefers-reduced-motion: no-preference) {
            .App-logo {
              animation: App-logo-spin infinite 20s linear;
            }
          }

          .App-header {
            background-color: #282c34;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            font-size: calc(10px + 2vmin);
            color: white;
          }

          .App-link {
            color: #61dafb;
          }

          @keyframes App-logo-spin {
            from {
              transform: rotate(0deg);
            }
            to {
              transform: rotate(360deg);
            }
          }
        `}</style>

      </BrowserRouter>
    </Fragment>
  );
}

const mapState = (state) =>{
  return {
    sideBar: state.store.sideBar,
  }
}

const mapDispatch = (dispatch) => {
  return {
    hideSide () {
      dispatch(actions.hideSide())
    }
  }
}

export default connect(mapState, mapDispatch)(App)

気がつけばsassとかreduxで書ける環境ができてると思います。
image.png

参考にしたもの:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0