経緯
react-spring のサンプルを試したくなったのでやってみました。
特にこのサンプルを見てみると、 react-scripts
というのを使っていたようなので、それに倣ってみました。
react-scripts
について軽く調べてみると、 create-react-app
に採用されているパッケージでありながら、 create-react-app
よりもシンプル。
一方、 webpack
内で babel-loader
や sass-loader
も処理される模様。
これならば、手軽にテストやモックアップを作るのにちょうど良さそうなので触ってみることにしました。
react-scripts
package.json
の scripts
に以下を指定。
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"test": "react-scripts test"
}
必要なファイル・ディレクトリを用意。
public/index.html
- JSの読み込みを既述する必要はない
src/index.js
- エントリポイント
これでコマンドを叩いて開発していけばOK。
scss
react-scripts
は webpack
の設定もなく sass-loader
も付いてくるようなので、試してみます。
"devDependencies": {
//略
"node-sass": "^4.14.*"
},
devDependencies
に足して yarn
。
@charset "utf-8";
@import "./base";
$bg-color: #17509f;
#root {
position: relative;
background-color: $bg-color;
height: 100vh;
}
例えばこんな src/scss/styles.scss
をに用意して、
import './scss/styles.scss';
src/App.js
で import
すればOK。
styled-components
scssが動くことを確認しましたが、折角なので styled-components
に入信。
"dependencies": {
//略
"styled-components": "^5.1.*"
},
dependencies
に足して yarn
。
import React from 'react';
import styled from 'styled-components';
const MainConatiner = styled.main.attrs(props => ({
headerHeight: props.headerheight || '60vh',
footerHeight: props.footerheight || '60px',
textColor: props.textcolor || 'white'
}))`
height: calc(100vh - (${props => props.headerHeight} + ${props => props.footerheight}));
padding-top: 5rem;
text-align: center;
`;
const Title = styled.h1.attrs(props => ({
textColor: props.textcolor || 'white'
}))`
font-size: 2rem;
color: ${props => props.textColor};
`;
const Main = props => {
const { config, commonVars } = props.data;
return (
<MainConatiner headerheight={commonVars.headerHeight} footerheight={commonVars.footerHeight}>
<Title textcolor={commonVars.textColor}>{config.title}</Title>
</MainConatiner>
);
};
export default Main;
普通に行けますね。
- 記法は慣れ
props
の初期値を決定しておく場合はattrs
を使用し、styled.ELEM.attrs(props => ({ textColor: props.textcolor || 'white' }))
のように記述する- 処理がなく即
return
で戻る場合は以下のように関数コンポーネントを記述することも可
import React from 'react';
//略
const Main = () => (
<MainConatiner>
<Title>タイトルサンプル</Title>
</MainConatiner>
);
export default Main;
props
親側。
import React from 'react';
import Main from './components/Main';
import './scss/styles.scss';
const App = () => {
const commons = {
config: {
title: 'サンプル'
},
commonVars: {
headerHeight: '60vh',
footerHeight: '56px',
textColor: 'white',
backgroundColor: '#17509f',
basePath: process.env.PUBLIC_URL || '',
backgroundImage: '/img/sample.png'
}
};
return (
<>
<Main data={commons} />
</>
);
};
export default App;
子側。
import React from 'react';
import styled from 'styled-components';
const MainConatiner = styled.main.attrs(props => ({
headerHeight: props.headerheight || '60vh',
footerHeight: props.footerheight || '60px',
textColor: props.textcolor || 'white'
}))`
height: calc(100vh - (${props => props.headerHeight} + ${props => props.footerheight}));
padding-top: 5rem;
text-align: center;
`;
const Title = styled.h1.attrs(props => ({
textColor: props.textcolor || 'white'
}))`
font-size: 2rem;
color: ${props => props.textColor};
`;
const Main = props => {
const { config, commonVars } = props.data;
return (
<MainConatiner headerheight={commonVars.headerHeight} footerheight={commonVars.footerHeight}>
<Title textcolor={commonVars.textColor}>{config.title}</Title>
</MainConatiner>
);
};
export default Main;
src/App.js
でcommons
なる変数を定義- 子コンポーネントに
data={}
の形で渡す- 子コンポーネントでは
props
として受け取る- 子コンポーネントでの
props
の書き換えは×
- 子コンポーネントでの
- 子コンポーネントでは
- 関数コンポーネントに引数名を記述 (ここでは
props
)- 関数コンポーネント内で
props.data
から取り出すstyled-components
に引数名={上述で取り出したプロパティ内のキーを指定}
の形で渡すstyled-components
内での既述は先述styled-components
の記述の通り
- 関数コンポーネント内で
なるほど。
ちなみに App.js
のようなルートのコンポーネントでは JSX に親要素が必要なため以下のようにブランクの要素でコンポーネントを挟む必要あり。
return (
<>
<Main data={commons} />
</>
);
応用( styled-components
+ props
)
import React from 'react';
import { useSpring, animated } from 'react-spring';
import styled from 'styled-components';
const CloudConatiner = styled(animated.div).attrs(props => ({
basePath: props.basepath || ''
}))`
position: absolute;
background-image: url(${props => props.basePath}/img/sample2.png);
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
opacity: 0.8;
will-change: transform;
&:first-of-type {
width: 400px;
height: 200px;
left: 55%;
top: 55%;
}
&:nth-of-type(2) {
width: 600px;
height: 300px;
left: 2%;
top: 8%;
}
&:last-of-type {
width: 500px;
height: 250px;
left: 40%;
top: 30%;
}
&:hover {
opacity: 1;
}
`;
//略
const Eyecatch = (props) => {
const { commonVars } = props.data;
//略
return (
[ 0, 1, 2 ].map((i) => {
return (
<CloudConatiner basepath={commonVars.basePath} />
);
})
);
};
export default Eyecatch;
styled-components
のテンプレートリテラル内はcssに準じるが、要素のネスト等一部scssっぽいことも可- 上述では
&:first-of-type
等 - プロパティのネストは不可
background-~
系をまとめることはできない
- 上述では
- カスタマイズされたコンポーネント(上述では
animated.div
)へのstyled-components
はstyled(animated.div)
の形で対応している- プレーンなタグ以外でも行けることが分かった
cross-env
ビルドして確認する際に、通常はcssやjsがルートディレクトリからの参照になってしまうためサブディレクトリだと正常な表示ができなくなることをすっかり忘れていました。
そこで、サブディレクトリでも動作するように cross-env
を導入しました。
"devDependencies": {
//略
"cross-env": "^7.0.*",
"node-sass": "^4.14.*"
},
devDependencies
に足して yarn
。
"scripts": {
"build": "cross-env PUBLIC_URL=/path/to/project/build/ react-scripts build",
}
npm scripts
の build
を変更。これ以外特に何も触らずに yarn build
するとサブディレクトリでも動作するようになりました。
応用( cross-env
の変数を React 内部で使用)
import React from 'react';
import Main from './components/Main';
import './scss/styles.scss';
const App = () => {
const commons = {
commonVars: {
//略
basePath: process.env.PUBLIC_URL || ''
//略
}
};
return (
<>
<Main data={commons} />
</>
);
};
export default App;
先ほどの arc/App.js
で、よく見ると process.env.PUBLIC_URL
の指定があります。
React 内でも cross-env
で渡した引数を参照することができるので、こうすることでパスの情報が package.json
と App.js
のように散在することなく、一元管理することが出来ました。
以上、簡単ですがペライチの React をサクッと作ることができました。
参考
react-spring
react-dom
styled-components
- styled-components: Basics
- The magic behind 💅 styled-components – Max Stoibers Blog
- How to pass props to components in React – RWieruch
react-scripts
cross-env
- Create React Appで作成したアプリを任意のサブディレクトリに配置する | NO MORE! 車輪の再発明
- dotenvとcross-envで環境変数を設定して開発環境の処理を切り替える | Tips Note by TAM
- Nuxtでcross-envを使い環境ごとに環境変数を分ける – Qiita