Reactの基礎４

https://qiita.com/hiro949/items/855e64ba7934d1774d91

https://qiita.com/hiro949/items/633a9086abfb1be274fe

https://qiita.com/hiro949/items/9fde00a08441c149f8fe

の続きです。

# ボタン操作

以下のようにしてボタンをクリックして関数を起動させることができます。次のコードではボタンを押すと関数handleClickが実行されて、コンソールに"I was clicked!"と表示されます。

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
    function handleClick() {
        console.log("I was clicked!")
    }
        
    return (
        <div className="container">
            <button onClick={handleClick}>Click me</button>
        </div>
    )
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

# マウスオーバー操作

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
    const ImgPath=require("./images/cat1.png");
    
    function handleOnMouseOver() {
        console.log("MouseOver")
    };
    
    return (
        <div className="container">
            <img 
                src={ImgPath} 
                onMouseOver={handleOnMouseOver}
                alt="logo" 
            />      
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

# 値の更新

Reactパッケージのメンバ関数useStateで定数に代入した値を変数のように変更することができます。
例えば次のコードをブラウザに出し、Yesの文字をクリックするとNoに代わります。

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App () {
    const [isImportant,setIsImportant] = React.useState("Yes");
    function handleClick() {
        setIsImportant("No");
    }
    return (
        <div className="state">
            <h1 className="state--title">Is state important to know?</h1>
            <div className="state--value" onClick={handleClick}>
                <h1>{isImportant}</h1>
            </div>
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

最初の出力：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/d9f424d2-4a95-9eef-c67e-39b9bd1ac4ce.png)

Yesの文字をクリックしたときの出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/a9e4e3d2-ac46-09a9-5074-7de90fba03ec.png)

もう少し複雑なものだと次のように値を増減させるコードも作れます。

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
    const [count, setCount] = React.useState(0);
    
    function add() {
        setCount(count+1);
    };
    
    function subtract() {
        setCount(count-1);
    };
    
    return (
        <div className="counter">
            <button className="counter--minus" onClick={subtract}>–</button>
            <div className="counter--count">
                <h1>{count}</h1>
            </div>
            <button className="counter--plus" onClick={add}>+</button>
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/dee60389-2257-5824-d096-605aa7aef397.png)

## コールバック関数

コールバック関数(関数が実行されると勝手に実行される関数)を更新の関数に設定して、複雑な更新をすることもできます。
次の例では関数addをコールバック関数で書き直してみました。prevCountに引数が渡されてコールバック関数が実行され、その結果がsetCountに渡されています。

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
    const [count, setCount] = React.useState(0);
    
    function add() {
        setCount(prevCount => prevCount + 1);
    };
    
    function subtract() {
        setCount(count-1);
    };
    
    return (
        <div className="counter">
            <button className="counter--minus" onClick={subtract}>–</button>
            <div className="counter--count">
                <h1>{count}</h1>
            </div>
            <button className="counter--plus" onClick={add}>+</button>
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

# 配列の要素の追加

ボタン操作で要素を追加してそれを反映させます。

```index.js
import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
    //配列とそれを上書きする関数
    const [things, setThings] = React.useState(["Thing 1", "Thing 2"]);
    
    function addItem() {
        //新しい要素
        const newThingText = `Thing ${things.length + 1}`;
        //配列の更新
        setThings(prevState => [...prevState, newThingText]);
    }
    
    //要素をJSXにする
    const thingsElements = things.map(thing => <p key={thing}>{thing}</p>);
    
    return (
        <div>
            <button onClick={addItem}>Add Item</button>
            {thingsElements}
        </div>
    )
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
```

addItemボタンをクリックすると配列が要素を追加したものに更新されてどんどん表示される要素が増えていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/d4c9dfa6-1133-e7a3-26f4-bd005f20b4ff.png)

# ３項演算子を使った切り替え
   先ほどのYes/NoではYesをクリックしたらNoになりますが、NoをクリックしてもYesにはなりません。これを解決します。

```index.js
let var = (条件判定)? (trueの場合): (falseの場合)
```

とすれば、変数varは条件判定に応じて２種類の値をとります。

今回は条件isGoingOutをReact.useStateで変更しながらその都度、三興演算子で吐き出す値を決めることにします。

```App.js
import './App.css';
import React from "react"

function App() {

  const [isGoingOut,setIsGoing] = React.useState(true);

  function changeMind(){
    setIsGoing(prevState => !prevState);
  };

  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div onClick={changeMind} className="state--value">
        <h1>{isGoingOut? "Yes": "No"}</h1>
      </div>
    </div>
  );
}


export default App;
//index.jsはcreate-react-appでできたものをそのまま使っている。
```

これを実行すると、Yes/Noの文字をクリックする度にYesとNoが切り替わります。

### 配列と要素の切り替えの組み合わせ

```components/Box.js
import React from 'react';

function Box(props){
    const [on,setOn] = React.useState(props.on);
    
    const styles = {
        backgroundColor: on? "#222222" : "transparent"
    };
    
    function toggle(){
        setOn(prevOn => !prevOn);
    };

    return (
        <div style={styles} className="box" key={props.id} onClick={toggle}></div>
    );
};

export default Box;
```

```boxes.js
const boxes = [
    {
        id: 1,
        on: true
    },   
    {
        id: 2,
        on: false
    },   
    {
        id: 3,
        on: true
    },   
    {
        id: 4,
        on: true
    },   
    {
        id: 5,
        on: false
    },   
    {
        id: 6,
        on: false
    },   
];

export default boxes;
```

```App.js
import React from 'react';
import './App.css';
import boxes from './boxes';
import Box from './components/Box';

function App(props) {
  const [squares, setSquares] = React.useState(boxes);

  const squareElements = squares.map(square => (
    <Box key={square.id} on={square.on} />
  ));

  return (
    <main>
        {squareElements}
    </main>
  );
}

export default App;
```

#### 出力結果

これを実行すると６つの四角い箱が表示されて、クリックすると白黒が反転します。

初期状態：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/81a2593a-8905-56c8-37ec-3fa37e92dc9f.png)

左から4番目と6番目の箱をクリック：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2445529/1b3879c0-698a-29f6-fb6f-b468eb1073d9.png)

# 参考記事
- https://scrimba.com/learn/learnreact
- https://ja.reactjs.org/