我一直在使用以前使用的集成Redux和Firebase数据库的样板来设置网站/ React App。但是,我是第一次在使用此样板的项目中使用React Hooks。到目前为止,我从Firebase RT-DB提取数据并将其与useState和useEffect一起使用都没有问题。现在,我想重构代码以将应用程序的状态存储在Redux中,但仍然使用功能组件并利用Hooks。
我很难将所有内容放在一起。
目前,我的设置如下所示:我不对Firebase中的任何数据进行身份验证,而直接将数据拉入。我已经包含了我的主页组件作为示例,该组件具有来自Firebase db的2个状态/数据的基本部分} & {姓}。
为了澄清我的问题,我在从动作生成器内部的实时数据库中获取数据,然后将其分派给reducer函数时遇到了麻烦。
我已经包括了我认为动作应该是什么样的,但是我不确定这是正确的,然后是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'));
configureStore.js
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 };
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 };
以下是移植本地组件状态并useEffect
回调到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
};
定义您的减速器。该FETCH_DATA
操作将启动异步操作以获取数据,清除任何当前错误状态并将其设置loading
为true。成功或失败后,将清除加载状态,并存储名称数据或设置错误值。
const initialState = {
error: false,
loading: false,
firstName: null,
lastName: null,
};
const reducer = (state = initialState, action) => {
switch(action.type) {
case "FETCH_DATA_LOADING":
return {
...state,
loading: action.payload,
};
case "FETCH_DATA_SUCCESS":
return {
...state,
error: false,
...action.payload, // ...{ firstName, lastName }
};
case "FETCH_DATA_FAILURE":
return {
...state,
error: true,
};
default:
return state;
}
};
将减速器添加到存储中。
import userReducer from './path/to/reducer/above';
const reducers = combineReducers({
user: userReducer,
});
连线HomePage
至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>
)
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句