对不起,我的英语不好。我在布局组件中使用react和redux.i调度getTags操作。问题是在调用getData操作之后,在组件渲染之后调用了getDataSuccess操作。所以我的数据为空。 我如何确定已获取数据并渲染组件?
布局:
function DashboardLayout({
children,
showSideBar,
backgroundColor,
getTagsFromServer,
getCategoriesFromServer,
}) {
getTagsFromServer();
getCategoriesFromServer();
return (
<StyledDashbordLayout>
<NavBar />
<SideBarDrawer />
<Grid container className="container">
{showSideBar && (
<Grid item className="sidebar-section">
<SideBar />
</Grid>
)}
<Grid item className="content">
{children}
</Grid>
</Grid>
</StyledDashbordLayout>
);
}
DashboardLayout.propTypes = {
children: PropTypes.node.isRequired,
showSideBar: PropTypes.bool.isRequired,
backgroundColor: PropTypes.string,
getTagsFromServer: PropTypes.func,
getCategoriesFromServer: PropTypes.func,
};
function mapDispatchToProps(dispatch) {
return {
dispatch,
getTagsFromServer: () => dispatch(getTags()),
getCategoriesFromServer: () => dispatch(getCategories()),
};
}
const withConnect = connect(
null,
mapDispatchToProps,
);
export default compose(withConnect)(DashboardLayout);
传奇:
import { call, put, takeLatest } from 'redux-saga/effects';
function* uploadVideo({ file }) {
try {
const { data } = yield call(uploadVideoApi, { file });
yield put(uploadFileSuccess(data));
} catch (err) {
yield put(uploadFileFail(err));
}
}
function* getTags() {
const { data } = yield call(getTagsApi);
console.log(data, 'app saga');
yield put(getTagsSuccess(data));
}
function* getCategories() {
const { data } = yield call(getTCategoriesApi);
yield put(getCategoriesSuccess(data));
}
// Individual exports for testing
export default function* appSaga() {
yield takeLatest(UPLOAD_VIDEO, uploadVideo);
yield takeLatest(GET_TAGS, getTags);
yield takeLatest(GET_CATEGORIES, getCategories);
}
这是我的选择框组件,它从存储中获取空数据:
import React, { useState } from 'react';
function UploadFileInfo({ tags, categories }) {
return (
<Paper square className={classes.paper}>
<Tabs
onChange={handleChange}
aria-label="disabled tabs example"
classes={{ indicator: classes.indicator, root: classes.root }}
value={tab}
>
<Tab
label="مشخصات ویدیو"
classes={{
selected: classes.selected,
}}
/>
<Tab
label="تنظیمات پیشرفته"
classes={{
selected: classes.selected,
}}
/>
</Tabs>
{tab === 0 && (
<Grid container className={classes.info}>
<Grid item xs={12} sm={6} className={classes.formControl}>
<label htmlFor="title" className={classes.label}>
عنوان ویدیو
</label>
<input
id="title"
type="text"
className={classes.input}
onChange={e => setValue('title', e.target.value)}
defaultValue={data.title}
/>
</Grid>
<Grid item xs={12} sm={6} className={classes.formControl}>
<SelectBox
onChange={e => setValue('category', e.target.value)}
value={data.category}
label="دسته بندی"
options={converItems(categories)}
/>
</Grid>
<Grid item xs={12} className={classes.textAreaWrapper}>
<label htmlFor="info" className={classes.label}>
توضیحات
</label>
<TextField
id="info"
multiline
rows={4}
defaultValue={data.info}
variant="outlined"
classes={{ root: classes.textArea }}
onChange={e => setValue('info', e.target.value)}
/>
</Grid>
<Grid item xs={12} sm={6} className={classes.formControl}>
<SelectBox
onChange={e => {
if (e.target.value.length > 5) {
console.log('hi');
setError(
'tags',
'تعداد تگ ها نمی تواند بیشتر از پنج عدد باشد',
);
return;
}
setValue('tags', e.target.value);
}}
value={data.tags}
label="تگ ها"
options={converItems(tags)}
multiple
onDelete={id => deleteTagHandler(id)}
error={errors.tags}
/>
</Grid>
</Grid>
)}
{tab === 1 && 'دومی'}
<Dump data={data} />
</Paper>
);
}
const mapStateToProps = createStructuredSelector({
tags: makeSelectTags(),
categories: makeSelectCategories(),
});
const withConnect = connect(
mapStateToProps,
null,
);
export default compose(withConnect)(UploadFileInfo);
答案 0 :(得分:0)
使用您的函数在React.useEffect内调用API。
您所有的API调用都应位于useEffect
挂钩内。
有关useEffect的更多信息,请阅读this
function DashboardLayout({
children,
showSideBar,
backgroundColor,
getTagsFromServer,
getCategoriesFromServer,
}) {
React.useEffect(() => {
getTagsFromServer();
getCategoriesFromServer();
}, []);
return (
<StyledDashbordLayout>
<NavBar />
<SideBarDrawer />
<Grid container className="container">
{showSideBar && (
<Grid item className="sidebar-section">
<SideBar />
</Grid>
)}
<Grid item className="content">
{children}
</Grid>
</Grid>
</StyledDashbordLayout>
);
}
答案 1 :(得分:0)
如果我正确理解了您的问题,则您正在询问如何保护options={converItems(tags)}
的{{1}}中SelectBox
的选项UploadFileInfo
或{{1 }}在尚未提取数据时赋值。
有一些选项可以防止null
或undefined
的值。
最简单的方法是为null
提供默认的后备值。在这里,我假设undefined
是一个数组,但是它们可以是任何东西,因此请根据您的需要进行调整。
tags
或tags
时内联options={converItems(tags || [])
options={converItems(tags ?? [])
中回退返回值的一部分另一种常见模式是条件渲染,其中function UploadFileInfo({ tags = [], categories })
可能是初始的redux状态值,因此您只需等待它 不为空 即可渲染用户界面
如果没有标签,则早期返回null
makeSelectTags
常规渲染null
function UploadFileInfo({ tags, categories }) {
if (!tags) return null;
return (
<Paper square className={classes.paper}>
...
SelectBox
中获取数据调用的附带说明当您将函数调用直接放置在函数主体中时,它们 会在任何时候被调用 反应决定“渲染”组件以执行任何DOM差异等...几乎在任何时候{tags ? (
<SelectBox
...
/>
) : null
}
都会进行数据提取,这可能会产生意想不到的影响。因此,反应功能成分被认为是没有副作用的纯功能。在安装组件时(或在需要在其他特定条件下调用的情况下,具有适当的依赖性),将所有获取数据的调用放置在仅被称为 一次 的效果挂钩中。>
DashboardLayout