背景
我正在使用React-Redux和React Hooks进行项目。
我有一个组件,该组件调度一个动作fetchCollectionData()
,该组件首先调度一个动作requestCollectionData()
,该动作将reducer的waiting属性更新为true。然后fetchCollectionData()
发出超级代理请求,以从服务器获取数据。响应返回后,fetchCollectionData()
调度另一个动作receiveCollectionData()
,该动作将使用结果更新reducer并将waiting属性设置为false。 API结果将带回的数据向下传递到子组件中的表。
问题:useDispatch()无限循环地调度fetchCollectionData()
操作。我只希望在组件安装时将此动作调度一次。
尝试:我曾尝试使用useEffect()钩子useEffect(fetchCollectionData(), [])
,但收到一条错误消息,指出useEffect不应用于承诺。
错误文本:
Warning: An effect function must not return anything besides a function, which is used for clean-up.
It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately:
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
in ContainerComponent (created by Context.Consumer)
in Route (at App.js:35)
in Switch (at App.js:33)
in div (at App.js:20)
in Router (created by BrowserRouter)
in BrowserRouter (at App.js:19)
in App (at Root.js:8)
in Provider (at Root.js:7)
in Root (at src/index.js:8)
我尝试将操作更改为export async function fetchCollectionData()
,但这导致我遇到更多错误。
父组件
export const ContainerComponent = () => {
const dispatch = useDispatch();
dispatch(actions.fetchCollectionData());
const data = useSelector(state => state.accountMaintenanceReducer.result);
const rows = data ? data : [];
return (
<div style={containerStyle}>
<div className="section-header">
<span>Account Maintenance</span>
</div>
<TableComponent rows={rows} />
</div>
);
};
子组件
import React from "react";
import { Table, TableHead, TableBody, TableRow, TableCell } from '@material-ui/core';
const columns = [,
{name: 'Primary Owner', key: 'owner'},
{name: 'Mailing Address', key: 'address'},
];
const dataToRows = (data) => {
if (data.rows.length) {
return data.rows.map(row => {
const index = row.ownerAndAddress.indexOf(String.fromCharCode(13));
const owner = row.ownerAndAddress.substring(0, index);
const address = row.ownerAndAddress.substring(index + 2);
return {
owner: owner,
address: address,
}
});
}
};
export const TableComponent = (data) => {
const rows = dataToRows(data);
return (
<Table>
<TableHead>
<TableRow>
{columns.map(column => (
<TableCell key={columns.indexOf(column)}>
{column.name}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{ rows ?
rows.map(row => (
<TableRow key={rows.indexOf(row)}>
{ Object.keys(row).map(cell => (
<TableCell className={cell} key={cell}>
{row[cell]}
</TableCell>
))}
</TableRow>
)) :
<TableRow>
<TableCell>No Data</TableCell>
</TableRow>
}
</TableBody>
</Table>
);
};
动作
export function receiveCollectionData(body) {
return {
type: 'RECEIVE_COLLECTION_DATA',
result: body,
}
}
export function requestCollectionData() {
return {
type: 'REQUEST_COLLECTION_DATA',
}
}
export function fetchCollectionData() {
return dispatch => {
dispatch(requestCollectionData());
return request.get(`api/Accounts/GetCollectionBySearch?searchString=Smith`)
.then(res => res.body)
.then(body=> dispatch(receiveCollectionData(body)))
}
}
减速器
export default (state = {}, action) => {
switch (action.type) {
case 'GET_COLLECTION_DATA':
return {
...state,
waiting: true
};
case 'RECEIVE_COLLECTION_DATA':
return {
...state,
result: action.result,
waiting: false
};
default:
return state;
}
}
所需的解决方案:
我想做的是模仿componentDidMount()
的功能,并在组件安装后分派fetchCollectionData()
。似乎fetchCollectionData()
一旦解决,就会再次调度,从而导致无限循环。
免责声明:
目标是获得一种将React Hooks与Redux结合使用并且不依赖于类组件的解决方案。
答案 0 :(得分:0)
在父组件上
const dispatch = useDispatch();
useEffect(()=> dispatch(actions.fetchCollectionData(), []);
应该工作。 由于某些原因,当您尝试使用useEffect时,它似乎没有分派
答案 1 :(得分:0)
已更改:
const dispatch = useDispatch();
useEffect(()=> dispatch(actions.fetchCollectionData(), []);
收件人:
const dispatch = useDispatch();
useEffect(()=> {dispatch(actions.fetchCollectionData()}, []);
答案 2 :(得分:0)
对于你们中的那些人,上面的方法并没有解决它,useEffect中的一个简单的if语句可以解决它。就我而言,我的值最初为null,因此我想模仿旧的ComponentDidMount方法。这是简单明了的解决方案。
useEffect(() => {
if (yourvalue === null)
dispatch(actiontodispatch());
}, []);
关键部分是开头为null / false或其他任何值的值。不过,不确定性能。