Redux が理解できず実際にサンプルページを作ってみた


Redux が理解できず実際にサンプルページを作ってみた

日付:2021-12-20更新日:2021-12-20

目次

Redux 便利なのはわかるけど仕組みがイマイチわかってない気がする~

React でデータを使いまわすには、props や Context を使えばいいのですが、どこからでもアクセス可能でデータを一元管理できる Redux 。。

これで全ていける!という暴力的な考え方は置いといて、便利なのはわかるけどイマイチ仕組みが分かりづらい…と思ったので、超かんたんなサンプルページを作ることにしました。

インプットボックスに値を入れてボタンを押すと、テキストまたはリンク先が変更されるってだけの超シンプルなページです。

実際に作ったサンプルページ

ソースコードはこちら>Git

画像:実際に作ったサンプルページ。インプットボックスに値を入れてボタンを押すと、テキストまたはリンク先が変更される

やったこと

ステップ1:React プロジェクトを作る

当たり前ですけどね…

npx create-react-app my-app

ステップ2:reactとreact-reduxをインストール

作成したプロジェクトディレクトリ(my-app)に移動してreactとreact-reduxをインストール。

ReactでReduxを利用するために二つ必要。

npm install redux react-redux

ステップ3:Store(データの保管場所)とReducer(データの更新担当)の作成

作った場所は、/store/index.js です。
Storeの値(初期値)は、リンク先のURL(linkUrl)とリンクテキスト(linkText)の二つを State に設定。
どのタイミングでデータを書き換えるのかを担当するReducerは、Action から受け取ったメッセージにあったデータを更新するように switch で記載していきます。
Git sauce

import { createStore } from "redux";

// 初期State
const initialState = {
linkUrl: 'https://www.yahoo.co.jp/',
linkText: 'Yahoo',
}

// Reducer処理 どのタイミングでデータを書き換えるのか
const reducer = (state = initialState, action) => {
    switch (action.type) {
        //action からメッセージ CHANGE_LINK_URL を受け取ったら
        case 'CHANGE_LINK_URL': {
            // initialState の linkUrl を action.payload.value に変更
    return {...state,linkUrl:action.payload.value}
    }
    case 'CHANGE_LINK_TEXT': {
            return {...state,linkText:action.payload.value}
        }
        case 'CHANGE_LINK_BOTH': {
            return {...state,linkText:action.payload.text,linkUrl:action.payload.url}
    }
    default: {
    return state
    }
}
}

const store = createStore(reducer);

export default store;

ステップ4:Reducer にメッセージと指示を与える Action の作成

作った場所は、/actions/actions.js です。
アクションは、ボタンの数と同じ3つ。
リンク先のURLを変更する、リンクテキストを変更する、リンクテキストとURL両方を変更するの3つを記載。
Git sauce

// ./redux/AppActions.js
/**
* Action type
*/
const CHANGE_LINK_URL = "CHANGE_LINK_URL";
const CHANGE_LINK_TEXT = "CHANGE_LINK_TEXT";
const CHANGE_LINK_BOTH = "CHANGE_LINK_BOTH";


/**
*  Action creator
*/
export const changeLinkUrl = (value) => ({
type: CHANGE_LINK_URL,
payload: {
    value,
},
});

export const changeLinkText = (value) => ({
type: CHANGE_LINK_TEXT,
payload: {
    value,
},
});

export const changeLinkBoth = (text,url) => ({
type: CHANGE_LINK_BOTH,
payload: {
        text,
        url
},
});

ステップ5:Provider でコンテンツを括る

Redux の storeデータをどこでも使いまわせるようにするには Provider でコンポーネントをくくる必要があります。

その前に、①React-ReduxのProviderをインポートと②新しく作ったstoreをインポートをしています。

↓index.js Git sauce

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
//①React-ReduxのProviderをインポート
import { Provider } from "react-redux";
//②新しく作ったstoreをインポート
import store from "./store/index";

//④Provider でくくる。
ReactDOM.render(
<React.StrictMode>
    <Provider store={store}>
    <App />
    </Provider>
</React.StrictMode>,
document.getElementById("root")
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

ステップ6:コンポーネントファイルを作る

/components/LinkBlock.js にコンポーネントとして表示部分を分けました。

store から値を取得するために useSelector、Reducer にメッセージを送る為に useDispatch を使ったので、それぞれ import しています。
Action の命令も import しています。
そして、useDispatch使います宣言を18行目でしています。
Git sauce

import { React, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import {
changeLinkUrl,
changeLinkText,
changeLinkBoth,
} from "../actions/actions";
import './LinkBlock.css';

function LinkBlock() {
//input の値
const [inputLinkText, setInputLinkText] = useState("");
const [inputLinkURL, setInputLinkURL] = useState("");
//store から値を取得
const linkUrl = useSelector((state) => state.linkUrl);
const linkText = useSelector((state) => state.linkText);
//useDispatch使います宣言
const dispatch = useDispatch();
//命令
const changeURL = () => {
    if (inputLinkURL) {
    dispatch(changeLinkUrl(inputLinkURL));
    } else {
    alert("リンク先を入れてね");
    }
};
const changeText = () => {
    if (inputLinkText) {
    dispatch(changeLinkText(inputLinkText));
    } else {
    alert("テキストを入れてね");
    }
};
const changeBoth = () => {
    if (inputLinkURL && inputLinkText) {
    dispatch(changeLinkBoth(inputLinkText, inputLinkURL));
    } else {
    alert("値が足りません");
    }
};

return (
    <div className='Contents'>
    <p>
        <a href={linkUrl}>{linkText}</a>
    </p>
    <form action="" className="Form">
        <div className="Form__inputs">
        <div className="Form__input">
            <label htmlFor="linktext">リンクテキストを入れてください</label>
            <input
            id="linktext"
            type="text"
            value={inputLinkText}
            onChange={({ target: { value } }) => setInputLinkText(value)}
            placeholder="Link Text"
            />
        </div>
        <div className="Form__input">
            <label htmlFor="linkulr">リンクURLを入れてください</label>
            <input
            type="linkulr"
            value={inputLinkURL}
            onChange={({ target: { value } }) => setInputLinkURL(value)}
            placeholder="Link URL"
            />
        </div>
        </div>
        <div className="Form__btns">
        <button type="button" onClick={changeURL}>
            リンクを変更
        </button>
        <button type="button" onClick={changeText}>
            テキストを変更
        </button>
        <button type="button" onClick={changeBoth}>
            リンクとテキストを変更
        </button>
        </div>
    </form>
    </div>
);
}

export default LinkBlock;

ステップ7:コンポーネントファイルを読み込む

App.js に作ったコンポーネントを呼び込みます。
Git sauce

import './App.css';
//コンポーネントを呼ぶだけ。
import LinkBlock from "./components/LinkBlock";

function App() {
return (
        <div className="App">
            <LinkBlock></LinkBlock>
    </div>
);
}

export default App;

出来た!ので仕組みはわかったかな

今回、参考にしたページはReac初心者でも読めば必ずわかるReactのRedux講座です。

ほぼそのまんま書いた感じですが、やりたいことが数のカウントじゃなかったので、その辺り「えーえーえーーーっ」って言いながら変更してましたw。
サラッと出来たふうですけど、つまらないところでジタバタしてましたね
ははは σ(*´∀`照)

Redux を使う場面を考えると割とおおきなサイトでデータの取り回しをするという感じなので、こんな小さなサンプルページではまだまだイメージが遠いけど、基本が分かればやっていることが分かるのでまぁ一歩前進です!とこれからも前向きに頑張ります!