【Next.js】レイアウトを作っていく

components/Layout.js

import React, { Component } from 'react';
import Header from '../components/Header';
import Footer from '../components/Footer';
import style from '../static/Style';

class Layout extends Component {

    render() {
        return (<div>
            {style}
            <Header header={this.props.header}
                title={this.props.title} />
            {this.props.children}
            <Footer footer="copyright hogehoge."/>
        </div>)
    }
}
export default Layout;

components/Header.js

import React, {Component} from 'react';

class Header extends Component {
    render() {
        return (<header>
            <div>{this.props.header}</div>
            <h1>{this.props.title}</h1>
        </header>)
    }
}
export default Header;

components/Footer.js

import React, {Component} from 'react';

class Footer extends Component {
    render() {
        return (<footer>
            <div>{this.props.footer}</div>
        </footer>)
    }
}
export default Footer;

static/Style.js

export default <style>{`
    body {
        margin:10px;
        padding: 5px;
        color: #669;
    }
    header {
        font-size: 64pt;
        font-weight: bold;
        text-align:right;
        letter-spacing: -8px;
        color: #ddddff;
        margin: -32px 5px;
    }
    footer {
        color:#99c;
        font-size:12pt;
        text-align:right;
        border-bottom:1px solid #99c;
        margin: 50px 0px 10px 0px;
        position: relative;
        bottom: 10px;
        right: 10px;
        left: 10px;
    }
    h1 {
        font-size:68pt;
        font-weight:bold;
        text-align:right;
        letter-spacing:-8px;
        color:#f0f0f0;
        margin:-32px 0px;
    }
    p {
        margin:0px;
        color:#666;
        font-size:16pt;
    }
`}</style>

index.js

import Link from 'next/link';
import Layout from '../components/Layout';

export default () => (
    <Layout header="Next" title="Top page.">
        <p>Welcome to next.js!</p>
        <hr />
        <Link href="./other">
            <button>go to Other &gt;&gt;</button>
        </Link>
    </Layout>
);

other.js

import Link from 'next/link';
import Layout from '../components/Layout';


export default () => (
    <Layout header="Other" title="Other page.">
        <p>This is other page.</p>
        <hr />
        <Link href="./">
            <button>&lt;&lt; Back to Top</button>
        </Link>
    </Layout>
);

import React, { Component } from 'react';

class Image extends Component {
    constructor(props) {
        super(props);
        this.fname = "./static/" + props.fname;
        this.size = props.size + "px";
    }

    render() {
        return (
            <img width={this.size} border="1"
                src={this.fname} />
        );
    }
}
export default Image;

なるほど、面白いと言えば面白い。

【Next.js】基本的な使い方と特徴

– Next.jsはjsのみ。HTMLファイルは使わずに開発を行う
– Netx.jsでは、Reactとは異なり、複数ページ開発できる

{
    "scripts": {
        "dev": "next",
        "build": "next build",
        "start": "next start",
        "export": "next export"
    }
}

$ npm install –save next react react-dom

pages/index.js

export default () => <div>
    <h1>Next.js</h1>
    <div>Welcome to next.js!</div>
</div>

$ npm run dev

next.config.js

module.exports = {
    exportPathMap: function() {
        return {
            '/': {page: '/'}
        }
    }
}

$ npm run build

const h1 = {
    fontSize:'72pt',
    fontWeight:'bold',
    textAlign:'right',
    letterSpacing:'-8px',
    color:'#f0f0f0',
    margin:'-40px 0px'
}

const p = {
    margin:'0px',
    color:'#666',
    fontSize:'16pt'
}


export default () => <div>
    <h1 style={h1}>Next.js</h1>
    <p style={p}>Welcome to next.js!</p>
</div>

### 複数ページの開発
index.js

import Link from 'next/link';

const h1 = {
    fontSize:'72pt',
    fontWeight:'bold',
    textAlign:'right',
    letterSpacing:'-8px',
    color:'#f0f0f0',
    margin:'-40px 0px'
}

const p = {
    margin:'0px',
    color:'#666',
    fontSize:'16pt'
}


export default () => <div>
    <h1 style={h1}>Next.js</h1>
    <p style={p}>Welcome to next.js!</p>
    <hr />
    <div>
        <Link href="/other">
            Go to Other page &gt;&gt;
        </Link>
    </div>
</div>

other.js

import Link from 'next/link';

const h1 = {
    fontSize:'72pt',
    fontWeight:'bold',
    textAlign:'right',
    letterSpacing:'-8px',
    color:'#f0f0f0',
    margin:'-40px 0px'
}

const p = {
    margin:'0px',
    color:'#666',
    fontSize:'16pt'
}


export default () => <div>
    <h1 style={h1}>Next.js</h1>
    <p style={p}>This is Other page.</p>
    <hr />
    <div>
        <Link href="/">
            &lt;&lt;Back to Index page
        </Link>
    </div>
</div>

### Component
Counter.js

import React, { Component } from 'react';

export default class Counter extends Component {
    msgStyle = {
        fontSize:"16pt",
        backgroundColor:"#eef",
        padding:"5px"
    }

    constructor(props) {
        super(props);
        this.state = {
            counter:0,
            msg: 'counter: 0',
        };
        this.doAction = this.doAction.bind(this);
    }

    doAction() {
        this.setState((state) => {
            const num = state.counter + 1;
            return ({
                counter: num,
                msg: "counter: " + num
            });
        });
    }

    render() {
        return <p onClick={this.doAction}
            style={this.msgStyle}>
            {this.state.msg}
        </p>;
    }
}
import Counter from '../components/Counter';
import style from '../static/Style';

export default () => <div>
    {style}
    <h1>Next.js</h1>
    <p>Welcome to next.js!</p>
    <hr />
    <Counter />
</div>

Reactをより使いやすくした って感じやね

【React.js】コンポーネントの様々な機能

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  input = '';

  msgStyle = {
    fontSize:"20pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
  }
  inputStyle = {
    fontSize: "12pt",
    padding: "5px"
  }

  constructor(props) {
    super(props);
    this.state = {
      message:'type your name:'
    };
    this.doChange = this.doChange.bind(this);
    this.doSubmit = this.doSubmit.bind(this);
  }

  doChange(event) {
    this.input = event.target.value;
  }

  doSubmit(event) {
    this.setState({
      message: 'Hello, ' + this.input + '!!'
    });
    event.preventDefault();
  }
  render() {
    return <div className="App">
    <h1>React</h1>
    <h2>{this.state.message}</h2>
    <form onSubmit={this.doSubmit}>
      <label>
        <span style={this.inputStyle}></span>Message:
        <input type="text" style={this.inputStyle} onChange={this.doChange} required pattern="[A-Za-z _,.]+"/>
      </label>
      <input type="submit" style={this.inputStyle} value="Click" />
    </form>
  </div>;
  }
}

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  input = '';

  msgStyle = {
    fontSize:"20pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
  }
  constructor(props) {
    super(props);
    this.state = {
      message:'type your name:'
    };
    this.doCheck = this.doCheck.bind(this);
  }

  doCheck(event) {
    alert(event.target.value +
      "は長すぎます。(最大10文字)"
    );
  }

  render() {
    return <div className="App">
    <h1>React</h1>
    <h2>{this.state.message}</h2>
    <Message maxlength="10" onCheck={this.doCheck} />
  </div>;
  }
}

class Message extends Component {
  inputStyle = {
    fontSize:"12pt",
    padding:"5px"
  }

  constructor(props) {
    super(props);
    this.doChange = this.doChange.bind(this);
  }

  doChange(e) {
    if(e.target.value.length > this.props.maxlength) {
      this.props.onCheck(e);
      e.target.value =
        e.target.value.substr(0,this.props.maxlength);
    }
  }

  render() {
    return <input type="text" style={this.inputStyle} onChange={this.doChange} />
  }
}

export default App;

### コンテキスト

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

let data = {title: 'Title',
  message: 'this is sample message.'
};

const SampleContext = React.createContext(data);

class App extends Component {

  render() {
    return <div className="App">
    <h1>Context</h1>
    <Title />
    <Message />
  </div>;
  }
}

class Title extends Component {
  static contextType = SampleContext;

  render() {
    return (
      <div>
        <h2>{this.context.title}</h2>
      </div>
    );
  }
}

class Message extends Component {
  static contextType = SampleContext;

  render() {
    return (
      <div>
        <p>{this.context.message}</p>
      </div>
    )
  }
}

export default App;
import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

let theme = {
  light: {
    backgroundColor: "#eef",
    color: "#006",
    padding:"10px",
  },
  dark: {
    backgroundColor:"#006",
    color:"#eef",
    padding:"10px",
  }
};

const ThemeContext = React.createContext(theme.dark);

class App extends Component {

  static contextType = ThemeContext;

  render() {
    return <div className="App" style={this.context}>
    <h1>Context</h1>
    <Title value="Content page" />
    <Message value="This is Content sample."/>
    <Message value="これはテーマのサンプルです。"/>
  </div>;
  }
}

class Title extends Component {
  static contextType = ThemeContext;

  render() {
    return (
      <div>
        <h2 style={this.context}>{this.props.value}</h2>
      </div>
    );
  }
}

class Message extends Component {
  static contextType = ThemeContext;

  render() {
    return (
      <div>
        <p style={this.context}>{this.props.value}</p>
      </div>
    )
  }
}

export default App;

【React.js】プロパティとステート

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  data = [];

  msgStyle = {
    fontSize:"20pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
  }
  area = {
    width: "500px",
    height: "500px",
    border: "1px solid blue"
  }

  constructor(props) {
    super(props);
    this.state = {
      list: this.data
    };
    this.doAction = this.doAction.bind(this);
  }

  doAction(e) {
    let x = e.pageX;
    let y = e.pageY;
    this.data.push({x:x, y:y});
    this.setState({
      list:this.data
    });
  }

  draw(d) {
    let s = {
      position:"absolute",
        left: (d.x - 25) + "px",
        top:(d.y - 25) + "px",
        width: "50px",
        height: "50px",
        backgroundColor: "#66f3",
    };
    return <div style={s}></div>
  }

  render() {
    return <div className="App">
    <h1>React</h1>
    <h2 style={this.msgStyle}>show rect. </h2>
    <div style={this.area} onClick={this.doAction}>
      {this.data.map((value) => this.draw(value))}
    </div>
  </div>;
  }
}

export default App;

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  data = [
    "This is list sample",
    "これはリストのサンプルです。",
    "配列をリストに変換します。"
  ];

  msgStyle = {
    fontSize:"20pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
  }

  constructor(props) {
    super(props);
    this.state = {
      list: this.data
    };
  }

  render() {
    return <div className="App">
    <h1>React</h1>
    <h2 style={this.msgStyle}>show list.</h2>
    <List title="サンプル・リスト" data={this.data} />
  </div>;
  }
}

class List extends Component {
  number = 1;

  title = {
    fontSize:"20pt",
    fontWeight:"bold",
    color:"blue",
  };

  render() {
    let data = this.props.data;
    return (
      <div>
        <p style={this.title}>{this.props.title}</p>
        <ul>
          {data.map((item) =>
            <Item number={this.number++} value={item} key={this.number} />
            )}
        </ul>
      </div>
    );
  }
}

class Item extends Component {
  li = {
    listStyleType:"square",
    fontSize:"16pt",
    color:"#06",
    margin:"0px",
    padding: "0px",
  }
  num = {
    fontWeight:"bold",
    color:"red"
  }

  render() {
    return (
      <li style={this.li}>
        <span style={this.num}>[{this.props.number}]</span>
         {this.props.value}
      </li>
    )
  }
}
export default App;

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  input = '';

  msgStyle = {
    fontSize:"20pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
  }

  constructor(props) {
    super(props);
    this.state = {
      message:'type your name:'
    };
    this.doChange = this.doChange.bind(this);
    this.doSubmit = this.doSubmit.bind(this);
  }

  doChange(event) {
    this.input = event.target.value;
  }

  doSubmit(event) {
    this.setState({
      message: 'Hello, ' + this.input + '!!'
    });
    event.preventDefault();
  }
  render() {
    return <div className="App">
    <h1>React</h1>
    <Message title="Children">
      これはコンポーネント内のコンテンツです。
      マルでテキストを分割し、リストにして表示します。
      改行は必要ありません。
    </Message>
  </div>;
  }
}

class Message extends Component {
  li = {
    fontSize:"16pt",
    color:"#06",
    margin:"0px",
    padding: "0px",
  }

  render() {
    let content = this.props.children;
    let arr = content.split('。');
    let arr2 = [];
    for(let i = 0; i < arr.length;i++){
      if(arr[i].trim() != '') {
        arr2.push(arr[i]);
      }
    }
    let list = arr2.map((value,key) => (
      <li style={this.li} key={key}>{value}.</li>
    ));
    return <div>
      <h2>{this.props.title}</h2>
      <ol>{list}</ol>
    </div>
  }
}
export default App;

【React.js】プロジェクトでコンポーネントの開発

App.js

import React, {Component} from 'react';
import './App.css';

class App extends Component {

  render() {
    return <div className="App">
    <h1>React</h1>
    <Rect x="50" y="50" w="150" h="150" c="cyan" />
    <Rect x="150" y="100" w="150" h="150" c="magenta" />
    <Rect x="100" y="150" w="150" h="150" c="black" />
  </div>;
  }
}

class Rect extends Component {
  x = 0;
  y = 0;
  width = 0;
  height = 0;
  color = "white";
  style = {};

  constructor(props) {
    super(props);
    this.x = props.x;
    this.y = props.y;
    this.width = props.w;
    this.height = props.h;
    this.color = props.c;
    this.style = {
      backgroundColor:this.color,
      position:"absolute",
      left:this.x + "px",
      top:this.y + "px",
      width:this.width + "px",
      height:this.height + "px"
    }
  }
  render(){
    return <div style={this.style}></div>
  }
}

export default App;

### ファイルの分割
Rect.js

import React, {Component} from 'react';

class Rect extends Component {
    x = 0;
    y = 0;
    width = 0;
    height = 0;
    color = "white";
    style = {};
  
    constructor(props) {
      super(props);
      this.x = props.x;
      this.y = props.y;
      this.width = props.w;
      this.height = props.h;
      this.color = props.c;
      this.radius = props.r;
      this.style = {
        backgroundColor:this.color,
        position:"absolute",
        left:this.x + "px",
        top:this.y + "px",
        width:this.width + "px",
        height:this.height + "px",
        borderRadius:this.radius + "px"
      }
    }
    render(){
      return <div style={this.style}></div>
    }
  }

export default Rect;

App.js

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  render() {
    return <div className="App">
    <h1>React</h1>
    <Rect x="50" y="50" w="150" h="150" c="cyan" r="50" />
    <Rect x="150" y="100" w="150" h="150" c="magenta" r="75" />
    <Rect x="100" y="150" w="150" h="150" c="black" r="25" />
  </div>;
  }
}

export default App;

### State

import React, {Component} from 'react';
import Rect from "./Rect";
import './App.css';

class App extends Component {

  msgStyle = {
    fontSize:"24pt",
    color:"#900",
    margin:"20px 0px",
    padding: "5px",
    borderBottom: "2px solid #900"
  }

  constructor(props) {
    super(props);
    this.state = {
      msg: 'Hello Component.',
    };
  }

  render() {
    return <div className="App">
    <h1>React</h1>
    <p style={this.msgStyle}>{this.state.msg}</p>
    <p style={this.msgStyle}>{this.props.msg}</p>
  </div>;
  }
}
  constructor(props) {
    super(props);
    this.state = {
      msg: 'Hello',
    };
    let timer = setInterval(() => {
      this.setState((state) => ({
        msg: state.msg + "!"
      }));
    }, 10000);
  }
  constructor(props) {
    super(props);
    this.state = {
      counter:0,
      msg: 'count start!',
    };
    this.doAction = this.doAction.bind(this);
  }

  doAction(e) {
    this.setState((state) => ({
      counter: state.counter + 1,
      msg: 'count: ' + state.counter
    }));
  }

  render() {
    return <div className="App">
    <h1>React</h1>
    <p style={this.msgStyle}>{this.state.msg}</p>
    <button style={this.btnStyle} onClick={this.doAction}>Click</button>
  </div>;
  }

【React.js】コンポーネントの理解

let dom = document.querySelector('#root');

const msg = {
    fontSize: "20pt",
    fontWeight: "bold",
    padding: "10px",
    color: "white",
    backgroundColor: "darkblue"
};

function Welcome(props) {
    return <p style={msg}>Hello React!!</p>;
}

let el = (
    <div>
        <Welcome />
    </div>
);
ReactDOM.render(el, dom);

### 属性の使用

let dom = document.querySelector('#root');

const msg1 = {
    fontSize: "20pt",
    padding: "10px",
    border: "double 5px magenta"
};

const msg2 = {
    fontSize: "16pt",
    fontWeight: "bold",
    padding: "10px",
    backgroundColor: "cyan"
};

function Welcome(props) {
    return <p style={props.style}>Hello, {props.name}!!</p>;
}

let el = (
    <div>
        <Welcome name="Taro" style={msg1} />
        <Welcome name="Hanako" style={msg2} />
    </div>
);
ReactDOM.render(el, dom);

### 計算するコンポーネント

let dom = document.querySelector('#root');

const msg = {
    fontSize: "16pt",
    fontWeight: "bold",
    padding: "10px",
    color: "white",
    backgroundColor: "darkblue"
};

function Calc(props) {
    let total = 0;
    for (let i = 1; i <= props.number; i++) {
        total += i;
    }
    return <p style={msg}>1から{props.number}までの合計は、「{total}」です。</p>;
}

let el = (
    <div>
        <Calc number="100" />
        <Calc number="200" />
        <Calc number="300" />
    </div>
);
ReactDOM.render(el, dom);

let dom = document.querySelector('#root');

class Rect extends React.Component {
    x = 0;
    y = 0;
    width = 0;
    height = 0;
    color = "white";
    style = {};

    constructor(props) {
        super(props);
        this.x = props.x;
        this.y = props.y;
        this.width = props.w;
        this.height = props.h;
        this.color = props.c;
        this.style = {
            backgroundColor:this.color,
            position:"absolute",
            left:this.x + "px",
            top:this.y + "px",
            width:this.width + "px",
            height: this.height + "px"
        }
    }

    render() {
        return <div style={this.style}></div>;
    }
}

let el = (
    <div>
        <Rect x="100" y="100" w="100" h="100" c="cyan" />
        <Rect x="150" y="150" w="100" h="100" c="magenta" />
    </div>
);
ReactDOM.render(el, dom);