Reactを学ぶ8

公式の1~9までをなぞった。 https://ja.reactjs.org/docs/hello-world.html
作業時間:4時間 経過時間:28.5時間
以下のコマンドでお手軽にプロジェクトを作れた。
create-react-app
create-react-appとは。 npm run testすると、Jestが走った。 コマンドすると、オプションが複数あった。
なんか良い感じに隠蔽してくれているらしい。 npm run ejectすると、隠蔽されていた設定ファイル等がむき出しになる。 カスタマイズするには、これを実行してからできる。
bashとzshが生きているのが酷いが、とりあえずnpmを生き返すために、調整だけした。
open ~/.bash_profile
source ~/.bash_profile
open ~/.zprofile
source ~/.zprofile
create-react-app
メモ
ReactDOM.render(
<React.StrictMode> //"use strict";
<App />
</React.StrictMode>,
document.getElementById('root')
);
imageをインポートすると、相対パスが返される。
import from '{image path}'
cssをインポートすると、どうなっているんだろうか。 中を見たが、空のオブジェクトが返される。 だけど、cssは適用されている。 どこで何が解決されているのだろう?
import a from './App.css';
function App(){
console.log(a)
return (
...
)
}
props
コンポーネントの名前は大文字から始めないと有効じゃない。
JSX とは、つまるところ React.createElement(component, props, ...children) の糖衣構文にすぎません。
propsはオブジェクト。コンポーネント定義で関数を定義しているが、やりとりするデータはオブジェクトでやりとしている。 糖衣構文を使用している場合は、背景をしった方がいい。でないと、データの流れが追いにくかった。
propsは読み取り専用であること。
stateとライフサイクル
class Clock extends React.Component{
constructor(props){
super(props);
this.state = {date: new Date()};
}
componentDidMount(){
this.timerID = setInterval(
() => this.tick(),
1000
)
}
componentWillUnmount(){
clearInterval(this.timerID);
}
tick(){
this.setState({
date: new Date()
})
}
render(){
return (
<div>
<h1>hello,world</h1>
<h2>it is {this.state.date.toLocaleTimeString()}</h2>
</div>
)
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
)
Event
class Toggle extends React.Component {
constructor(props){
super(props);
this.state = {isToggleOn: true};
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState(state =>({
isToggleOn: !state.isToggleOn
}))
}
render(){
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON': "OFF"}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
)
条件付きレンダー
const UserGreeting = props =>{
return <h1>welcome back!</h1>
}
const GuestGreeting = props => {
return <h1>please sign up</h1>
}
const Greeting = props =>{
const isLoggedIn = props.isLoggedIn;
if(isLoggedIn){
return <UserGreeting />
}
return <GuestGreeting />
}
const LoginButton = props =>{
return (
<button onClick={props.onClick}>
Login
</button>
)
}
const LogoutButton = props =>{
return (
<button onClick={props.onClick}>
Logout
</button>
)
}
class LoginControl extends React.Component {
constructor(props){
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false}
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick(){
this.setState({isLoggedIn: false})
}
render(){
const isLoggedIn = this.state.isLoggedIn;
let button;
if(isLoggedIn){
button = <LogoutButton onClick={this.handleLogoutClick} />
} else {
button = <LoginButton onClick={this.handleLoginClick} />
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
)
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
)
true && expressionはtrue,false && expressionはfalse
function MailBox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You hav {unreadMessages.length} unread messages;
</h2>
}
</div>
)
}
const messages = ['react','re:react','re:re: react'];
ReactDOM.render(
<MailBox unreadMessages={messages} />,
document.getElementById('root')
)
コンポーネントでnullを返せる
const WarningBanner = props =>{
if(!props.warn)return null;
return (
<div className="warning">
warning
</div>
)
}
class Page extends React.Component{
constructor(props){
super(props);
this.state = {showWarning: true};
this.handleToggleClick = this.handleToggleClick.bind(this)
}
handleToggleClick() {
this.setState(state => ({
showWarning: !state.showWarning
}))
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? 'Hide': 'Show'}
</button>
</div>
)
}
}
ReactDOM.render(
<Page />,
document.getElementById('root')
)
リストと key
listを作成する場合、key属性がいる。 keyがいる理由は、差分検出処理で機能するため。
const NumberList = props =>{
const numbers = props.numbers;
const listItems = numbers.map((number)=>
<li key={number.toString()}>{number}</li>
)
return (
<ul>{listItems}</ul>
)
}
const numbers = [1,2,3,4,5];
ReactDOM.render(
<NumberList numbers={numbers}/>,
document.getElementById('root')
)
mapでインライン化できる
const ListItem = props =>{
return <li>{props.value}</li>
}
const NumberList = props =>{
const numbers = props.numbers;
return (
<ul>
{numbers.map((number)=>
<ListItem key={number.toString()} value={number} />
)}
</ul>
)
}
const numbers = [1,2,3,4]
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
)
form
制御されたコンポーネント、stateでデータを管理する textareaはvalueで管理される
class NameForm extends React.Component {
constructor(props){
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value})
}
handleSubmit(event) {
alert('A name was submitted:' + this.state.value)
event.preventDefault();
}
render(){
return (
<form onSubmit={this.handleSubmit}>
<label>
pick your favorite:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
{/* <input type="text" value={this.state.value} onChange={this.handleChange} /> */}
{/* <textarea value={this.state.value} onChange={this.handleChange} /> */}
</label>
<input type="submit" value="Submit" />
</form>
)
}
}
computed property nameを知る。 オブジェクトのキーに変数を割り当てて使用するには、ブラケットを用いれば可能だった。
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this)
}
handleInputChange(event) {
const target = event.target;
const value = target.name = 'isGoing' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
})
}
render() {
return (
<form>
<label>
is going:
<input
name="isGoing"
type="checkbox"
checke={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
)
}
}
ReactDOM.render(
<Reservation />,
document.getElementById('root')
)