前提・実現したいこと
Reduxで値を管理しています。状態管理をしているデータをuseSelectorで取得したい。
発生している問題
useSelectorでデータを取得しようとすると二度同じコードが読まれます。
一度はカラのデータが返されて、二度目に実行され保存されているデータが取得されます。
環境
package.json
{ "name": "react-typescript-sass-webpack", "version": "0.1.0", "private": true, "dependencies": { "@reduxjs/toolkit": "^1.5.0", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "@types/jest": "^24.9.1", "@types/node": "^12.20.6", "@types/react": "^16.14.5", "@types/react-dom": "^16.9.11", "@types/react-redux": "^7.1.16", "@types/react-router-dom": "^5.1.7", "react": "^17.0.1", "react-dom": "^17.0.1", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "typescript": "^3.8.3" }, "scripts": { "start": "webpack serve", "build": "webpack" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "css-loader": "^5.1.3", "html-webpack-plugin": "^5.3.1", "mini-css-extract-plugin": "^1.3.9", "sass": "^1.32.8", "sass-loader": "^11.0.1", "style-loader": "^2.0.0", "ts-loader": "^8.0.18", "webpack": "^5.26.2", "webpack-cli": "^4.5.0", "webpack-dev-server": "^3.11.2" } }
該当のソースコード
webpack.config.js
const path = require('path') // const MODE = "production"; const MODE = "development"; const enabledSourceMap = MODE === "development"; // plugin const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: MODE, entry: "./src/main.tsx", output: { path: `${__dirname}/dist`, filename: "main.js", }, devServer: { contentBase: path.resolve(__dirname, 'dist'), publicPath: '/dist/', port: 3040, open: true, historyApiFallback: true, // without no routing }, module: { rules: [ { test: /.scss/, use: [ "style-loader", { loader: "css-loader?modules", options: { url: true, sourceMap: enabledSourceMap, importLoaders: 2, }, }, { loader: "sass-loader", options: { sourceMap: enabledSourceMap, }, }, ], }, { test: /.(gif|png|jpg|eot|wof|woff|ttf|svg)$/, type: "asset/inline", }, { test: /.tsx?$/, use: "ts-loader" } ] }, resolve: { extensions: [".ts", ".tsx", ".js", ".json"] }, target: ["web", "es5"], plugins: [ new HtmlWebpackPlugin({ publicPath: '', filename: 'index.html', template: 'src/html/index.html', }), ] };
tsconfig.json
{ "compilerOptions": { "sourceMap": true, "noImplicitAny": true, "allowJs": true, "strictNullChecks": true, "module": "ES6", "target": "ES2015", "jsx": "react", "allowSyntheticDefaultImports": true, "moduleResolution": "node", }, "include": [ "src", ], "exclude": [ "node_modules" ], }
main.tsx
// React import React, { useEffect } from 'react'; import * as ReactDOM from 'react-dom'; import { BrowserRouter, Switch, Route } from 'react-router-dom'; // Components import Top from './components/pages/Top'; import { login } from './common/redux/userSlice' // Redux import { Provider } from "react-redux" import { store } from './common/redux/store' import { useDispatch } from 'react-redux' const App: React.FC = () => { const dispatch = useDispatch(); useEffect(() => { dispatch( login({ uid: "test_uid", photoUrl: "test_phtho", displayName: "test_displayname", })) }, [dispatch]); return ( <BrowserRouter> <Switch> <Route exact path="/" component={Top} /> </Switch> </BrowserRouter> ); } ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.querySelector('#app'));
Top.tsx
import React from 'react'; // Componens import Footer from '../organisms/Footer'; import Header from '../organisms/Header'; // assets import style from '../../assets/scss/style.module.scss' // redux import { selectUser } from '../../common/redux/userSlice' import { useSelector } from 'react-redux' const Top: React.FC = () => { // 上記の画像はここのコード。二度読まれ、一度目は値を取得できていない。 const user = useSelector(selectUser); console.log(user.uid); return ( <> <Header /> <div className={style['title']}> トップページ </div> <Footer /> </> ); }; export default Top;
store.tsx
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit"; import userReducer from './userSlice' export const store = configureStore({ reducer: { user: userReducer, } }) export type RootState = ReturnType<typeof store.getState> export type AppThunk<ReturnType = void> = ThunkAction< ReturnType, RootState, unknown, Action<string> >; // export type AppDispatch = typeof store.dispatch;
userSlice.tsx
import { createSlice, PayloadAction } from "@reduxjs/toolkit" import { RootState } from "./store" interface USER { displayName: string; photoUrl: string; } export const userSlice = createSlice({ name: "user", initialState: { user: { uid: "", photoUrl: "", displayName: "" }, }, reducers: { login: (state, action) => { state.user = action.payload; }, logout: (state) => { state.user = { uid: "", photoUrl: "", displayName: "" } }, updateUserProfile: (state, action: PayloadAction<USER>) => { state.user.displayName = action.payload.displayName; state.user.photoUrl = action.payload.photoUrl; } } }) export const { login, logout, updateUserProfile } = userSlice.actions; export const selectUser = (state: RootState) => state.user.user; export default userSlice.reducer;
試したこと
以下、試しましたが現象は変わりませんでした。
- React.StrictModeを削除
- BrowserRouterを止めてみた
- Webpack4で試した。
宜しくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/03/19 01:58