Reactjs 重构React代码,使用Firebase RT数据库中的Redux状态&;复钩

Reactjs 重构React代码,使用Firebase RT数据库中的Redux状态&;复钩,reactjs,firebase,firebase-realtime-database,react-redux,react-hooks,Reactjs,Firebase,Firebase Realtime Database,React Redux,React Hooks,我一直在使用我以前使用过的模板建立一个网站/React应用程序,该模板集成了Redux和Firebase数据库。然而,我在第一次使用这个样板的项目中使用了React钩子。到目前为止,我从Firebase RT-DB获取数据并将其与useState和useEffect一起使用没有问题。我现在想重构代码,将我的应用程序状态存储在Redux中,但仍然使用功能组件和挂钩 我很难把所有的东西都放在一起 我的设置当前看起来像这样。。。我没有验证Firebase的任何数据,只是直接将数据拉入。我已经包括了我的

我一直在使用我以前使用过的模板建立一个网站/React应用程序,该模板集成了Redux和Firebase数据库。然而,我在第一次使用这个样板的项目中使用了React钩子。到目前为止,我从Firebase RT-DB获取数据并将其与useState和useEffect一起使用没有问题。我现在想重构代码,将我的应用程序状态存储在Redux中,但仍然使用功能组件和挂钩

我很难把所有的东西都放在一起

我的设置当前看起来像这样。。。我没有验证Firebase的任何数据,只是直接将数据拉入。我已经包括了我的主页组件作为一个例子,它有来自Firebase db{firstName}&{lastName}的2条基本状态/数据

为了澄清我的问题,我在从action generator内部的实时数据库中获取数据,然后将其分配给reducer函数时遇到了问题

我已经包括了我认为动作应该是什么样子,但我不确定这是否正确,以及减速器函数应该是什么样子

谢谢你的帮助

app.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store/configureStore';
import AppRouter, { history } from './routers/AppRouter';

// const store = configureStore();

const jsx = (
  <Provider store={store}>
    <AppRouter history={history} />
  </Provider>

);

ReactDOM.render(jsx, document.getElementById('app')); 
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';

export const reducers = combineReducers({

});

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

// store.js

export function configureStore(initialState = {}) {

  const store = createStore(reducers, initialState, composeEnhancers(applyMiddleware(thunk)), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

  return store;
}

export const store = configureStore();
homepage.js组件示例

import React, { useState, useEffect } from "react";
import database from '../firebase/firebase';

const HomePage = () => {

    const [firstName, setFirstName] = useState(firstName);
    const [lastName, setLastName] = useState(lastName);

    useEffect(() => {
        database.ref()
            .once('value')
            .then((snapshot) => {
                const data = snapshot.val();
                const { firstName, lastName } = data
                setFirstName(firstName)
                setLastName(lastName)
            })
            .catch((e) => {
                console.log('Error fetching data', e);
            });
    }, []);

    return (
         <div className="homepage-section__content">
            <HomePageTitle firstName={firstName} lastName={lastName} />
         </div>
    )
}

export { HomePage as default };
import React,{useState,useffect}来自“React”;
从“../firebase/firebase”导入数据库;
const主页=()=>{
const[firstName,setFirstName]=useState(firstName);
const[lastName,setLastName]=useState(lastName);
useffect(()=>{
database.ref()
.once('值')
。然后((快照)=>{
const data=snapshot.val();
常量{firstName,lastName}=data
setFirstName(名字)
setLastName(lastName)
})
.catch((e)=>{
console.log('Error fetching data',e);
});
}, []);
返回(
)
}
导出{默认主页};
homePageTitle.js组件

import React from 'react';

const HomePageTitle = (props) => (
    <React.Fragment>
        <h1>
            {props.firstName}
            <span>{props.lastName}</span>
        </h1>
    </React.Fragment>
);

export { HomePageTitle as default };

从“React”导入React;
const HomePageTitle=(道具)=>(
{props.firstName}
{props.lastName}
);
导出{HomePageTitle作为默认值};

以下是一种方法,您可以通过本地组件状态进行移植,并
useffect
回调到redux状态和操作

您可以定义一组数据获取启动、成功和失败操作

const setDataLoading = loading => ({
  type: "FETCH_DATA_LOADING",
  payload: loading,
});

const fetchDataSuccess = payload => ({
  type: "FETCH_DATA_SUCCESS",
  payload, // { firstName, lastName }
});

const fetchDataFailure = () => ({ type: "FETCH_DATA_FAILURE" });

const fetchData = () => dispatch => {
  dispatch(setDataLoading(true)); // <-- start loading
  return database.ref() // <-- return Promise chain
    .once('value')
    .then((snapshot) => {
      const { firstName, lastName } = snapshot.val();
      dispatch(fetchDataSuccess({ firstName, lastName }));
    })
    .catch((e) => {
      console.error('Error fetching data', e);
      dispatch(fetchDataFailure());
    })
    .finally(() => dispatch(setDataLoading(false))); // <-- complete loading
};
将减速机添加到存储

import userReducer from './path/to/reducer/above';

const reducers = combineReducers({
  user: userReducer,
});
主页连接到redux商店

const HomePage = () => {
  const dispatch = useDispatch();
  const { error, firstName, lastName, loading } = useSelector(state => state.user);

  useEffect(() => {
    dispatch(fetchData());
  }, []);

  return (
    <div className="homepage-section__content">
      {error && <div>Error fetching user name</div>}
      {loading ? (
        <LoadingSpinner />
      ) : (
        <HomePageTitle firstName={firstName} lastName={lastName} />
      )}
    </div>
  )
};
const主页=()=>{
const dispatch=usedpatch();
const{error,firstName,lastName,load}=useSelector(state=>state.user);
useffect(()=>{
分派(fetchData());
}, []);
返回(
{获取用户名时出错(&R)}
{加载(
) : (
)}
)
};

似乎您可以使用标准操作来分派操作以从DB获取,使用thunk处理异步逻辑,并分派成功操作以更新您的redux存储。你试过什么?你能包括你的行动和计划吗?你有什么特别的方面或问题吗?我还没有尝试过任何东西,因为我不知道怎么做。我知道有Redux钩子、useReducer和useSelector,但我不确定如何集成它们。这基本上是我的问题。我想我需要将数据库fetch移入一个操作,但是如何将它移入reducer和store,我知道该怎么做。
react redux
useDispatch
useSelector
挂钩,
useReducer
是一个标准的react挂钩,与redux无关(但应用了一个非常类似的模式)。如果您已经熟悉
react redux
,那么分派动作基本上与以前使用“mapDispatchToProps”时相同,只是现在它不再是道具,动作创建者也完全相同。如果使用钩子仍然有点混乱,您仍然可以使用您可能更熟悉的较旧的
connect
高阶组件。从这里,我们可以帮助它工作或转换为使用挂钩。是的,我正在尝试使用挂钩。这也是我第一次在Redux内部从firebase中获取数据,所以对我来说是全新的。任何帮助或指点都会很棒。这非常有效,解释也很棒!
const HomePage = () => {
  const dispatch = useDispatch();
  const { error, firstName, lastName, loading } = useSelector(state => state.user);

  useEffect(() => {
    dispatch(fetchData());
  }, []);

  return (
    <div className="homepage-section__content">
      {error && <div>Error fetching user name</div>}
      {loading ? (
        <LoadingSpinner />
      ) : (
        <HomePageTitle firstName={firstName} lastName={lastName} />
      )}
    </div>
  )
};