传奇在组件渲染后获取数据

时间:2020-09-09 03:42:00

标签: javascript reactjs redux react-redux

对不起,我的英语不好。我在布局组件中使用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);

2 个答案:

答案 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 }}在尚未提取数据时赋值。

解决方案

有一些选项可以防止nullundefined的值。

最简单的方法是为null提供默认的后备值。在这里,我假设undefined是一个数组,但是它们可以是任何东西,因此请根据您的需要进行调整。

  1. 在通过tagstags时内联
  2. 在函数签名options={converItems(tags || [])
  3. 作为options={converItems(tags ?? [])中回退返回值的一部分

另一种常见模式是条件渲染,其中function UploadFileInfo({ tags = [], categories })可能是初始的redux状态值,因此您只需等待它 不为空 即可渲染用户界面

  1. 如果没有标签,则早期返回null

    makeSelectTags
  2. 常规渲染null

    function UploadFileInfo({ tags, categories }) {
      if (!tags) return null;
    
      return (
        <Paper square className={classes.paper}>
          ...
    

关于在SelectBox中获取数据调用的附带说明

当您将函数调用直接放置在函数主体中时,它们 会在任何时候被调用 反应决定“渲染”组件以执行任何DOM差异等...几乎在任何时候{tags ? ( <SelectBox ... /> ) : null } 都会进行数据提取,这可能会产生意想不到的影响。因此,反应功能成分被认为是没有副作用的纯功能。在安装组件时(或在需要在其他特定条件下调用的情况下,具有适当的依赖性),将所有获取数据的调用放置在仅被称为 一次 的效果挂钩中。

DashboardLayout