Reactjs 重构React代码,使用Firebase RT数据库中的Redux状态&;复钩
我一直在使用我以前使用过的模板建立一个网站/React应用程序,该模板集成了Redux和Firebase数据库。然而,我在第一次使用这个样板的项目中使用了React钩子。到目前为止,我从Firebase RT-DB获取数据并将其与useState和useEffect一起使用没有问题。我现在想重构代码,将我的应用程序状态存储在Redux中,但仍然使用功能组件和挂钩 我很难把所有的东西都放在一起 我的设置当前看起来像这样。。。我没有验证Firebase的任何数据,只是直接将数据拉入。我已经包括了我的主页组件作为一个例子,它有来自Firebase db{firstName}&{lastName}的2条基本状态/数据 为了澄清我的问题,我在从action generator内部的实时数据库中获取数据,然后将其分配给reducer函数时遇到了问题 我已经包括了我认为动作应该是什么样子,但我不确定这是否正确,以及减速器函数应该是什么样子 谢谢你的帮助 app.jsReactjs 重构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的任何数据,只是直接将数据拉入。我已经包括了我的
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>
)
};