その2(stylus実験…動かない)
https://qiita.com/DaisukeNishi/items/57cb3a440ddfb876ee9a
その3
https://qiita.com/DaisukeNishi/items/78bdb0ec6af9aea204d2
※自分用boilerPlate
作ればいいじゃんgit clone
一発だよと思うじゃないですか。
一応、写経も兼ねて反芻してるです。
「感謝の正拳突き1日1万回」...じゃないですが、
毎日環境構築を反芻してたら型として覚えられると思った。
変な型が身についてしまったらゴメンなさい。
(↓グローバルインストールは初回のみ)
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
const { override,useBabelRc,useEslintRc,disableEsLint} = require("customize-cra");
module.exports = override(
useBabelRc(".babelrc.json"),
useEslintRc(".eslintrc.json"),
//disableEsLint()
);
NPMスクリプトを書き換える。
open 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
{
"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
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
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
対応あるだろうからpolyfill
とautoprefixer
は忘れずに
"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
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
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
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
は書き換える
//(省略)
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
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
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
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.js
をredux
対応版に書き換える
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
で書ける環境ができてると思います。
####参考にしたもの:
https://github.com/guts111/MyForum-React