redux-saga总是返回'undefined'

时间:2019-11-04 22:42:07

标签: reactjs redux redux-saga

我一直在尝试使用redux和redux-saga创建一个React应用,但是我一直无法使它工作,因此我总是得到undefined的值。

这是我的组件catalogs/index.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import CatalogHeader from './CatalogHeader';
import CircularProgress from '@material-ui/core/CircularProgress';
import {getCatalogs} from 'actions/Catalogs';
import IntlMessages from 'util/IntlMessages';
import CustomScrollbars from 'util/CustomScrollbars';


class Catalogs extends Component {

  constructor() {
    super();
    this.state = {
      anchorEl: null
    }
  }

  updateSearch = (evt) => {
    this.props.updateSearch(evt.target.value);
    this.onSearchTodo(evt.target.value)
  };

  render() {
    const {catalogsList} = this.props;

    return (
      <div className="app-wrapper">
        <div className="animated slideInUpTiny animation-duration-3">
          <div className="app-module">
            <div className="module-box">
              <div className="module-box-header">
                <CatalogHeader catalogsList={catalogsList}
                                placeholder="Buscar" user={this.props.user}
                                onChange={this.updateSearch.bind(this)}
                                value={this.props.searchTodo}/>
              </div>

            </div>
          </div>
        </div>
      </div>
    )
  }
}

const mapStateToProps = ({catalogs, settings}) => {
  const {width} = settings;
  const {catalogsList} = catalogs;
  return {
    width,
    catalogsList,
  }
};

export default connect(mapStateToProps, {
  getCatalogs,
})(Catalogs);

这是另一个组件catalogs/CatalogHeader.js

import React from 'react';
import IconButton from '@material-ui/core/IconButton';
import Button from '@material-ui/core/Button';
import {Dropdown, DropdownMenu, DropdownToggle, Popover} from 'reactstrap';
import SearchBox from 'components/SearchBox';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import Select from '@material-ui/core/Select';

class CatalogHeader extends React.Component {

  handleChange = name => event => {
    this.setState({[name]: event.target.value});
  };

  onSearchBoxSelect = () => {
    this.setState({
      searchBox: !this.state.searchBox
    })
  };

  constructor() {
    super();
    this.state = {
      anchorEl: undefined,
      searchBox: false,
      popoverOpen: false
    };
    this.toggle = this.toggle.bind(this);

  }

  toggle() {
    this.setState({
      popoverOpen: !this.state.popoverOpen
    });
  }

  printCatalogs(catalogs) {
    console.log(catalogs);
  }

  render() {
    const {catalogs} = this.props;

    return (
      <div className="module-box-header-inner catalogs-header">
        <div className="col-5 catalogs-header">
          <FormControl className="w-100 mb-2">
            {this.printCatalogs(this.props.catalogs)}
            <InputLabel htmlFor="age-simple">Seleccione Catálogo</InputLabel>
            <Select
              value={this.state.age}
              onChange={this.handleChange('age')}
              input={<Input id="ageSimple1"/>}>
              {catalogs.map(catalog =>
                <MenuItem key={catalog}>
                  {catalog}
                </MenuItem>,
              )}

              <MenuItem value="">
                <em>None</em>
              </MenuItem>
              <MenuItem value={10}>Ten</MenuItem>
              <MenuItem value={20}>Twenty</MenuItem>
              <MenuItem value={30}>Thirty</MenuItem>
            </Select>
          </FormControl>
        </div>
        <div className="module-box-header-right col-7 catalogs-header">
          <div className="search-bar right-side-icon bg-transparent d-none d-sm-block col-6">
            <div className="form-group">
              <input className="form-control border-0" type="search" placeholder="Buscar"/>
              <button className="search-icon"><i className="zmdi zmdi-search zmdi-hc-lg"/></button>
            </div>
          </div>
          <div className="col-6">
            <div className="catalogs-header catalogs-header-buttons">
              <Button variant="contained" className="jr-btn bg-white">
                <i className="zmdi zmdi-filter-list zmdi-hc-fw"/>
                <span>Filtrar</span>
              </Button>
              <Button variant="contained" className="jr-btn bg-white">
                <i className="zmdi zmdi-sort zmdi-hc-fw"/>
                <span>Ordenar</span>
              </Button>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default CatalogHeader;

这是我的操作文件:

import {
  GET_CATALOGS,
  GET_CATALOGS_SUCCESS,
  SHOW_MESSAGE
 } from 'constants/ActionTypes';

export const getCatalogs = (group) => {
  return {
    type: GET_CATALOGS,
    payload: group
  };
};

export const getCatalogsSuccess = (catalogs) => {
  return {
    type: GET_CATALOGS_SUCCESS,
    payload: catalogs
  }
};

export const showCatalogsMessage = (message) => {
  return {
    type: SHOW_MESSAGE,
    payload: message
  };
};

这是我的减速器文件:

import {
  GET_CATALOGS,
  SHOW_MESSAGE,
  HIDE_MESSAGE,
  GET_CATALOGS_SUCCESS
} from 'constants/ActionTypes';

const INIT_STATE = {
  loader: false,
  alertMessage: '',
  showMessage: false,
  catalogsList: null
};

export default (state=INIT_STATE, action) => {
  switch (action.type) {
    case GET_CATALOGS_SUCCESS: {
      return {
        ...state,
        loader: false,
        catalogsList: action.payload
      }
    }
    case SHOW_MESSAGE: {
      return {
        ...state,
        alertMessage: action.payload,
        showMessage: true,
        loader: false
      }
    }
    case HIDE_MESSAGE: {
      return {
        ...state,
        alertMessage: '',
        showMessage: false,
        loader: false
      }
    }
    default:
      return state;
  }
}

这是我的sagas文件:

import {all, call, fork, put, takeEvery} from "redux-saga/effects";
import {catalogs} from 'backend/Catalogs';
import {GET_CATALOGS} from "constants/ActionTypes";
import {getCatalogs, getCatalogsSuccess, showCatalogsMessage} from 'actions/Catalogs';

const getCatalogsRequest = async (group) => {
  await catalogs.getCatalogs(group)
    .then(catalogsList => catalogsList)
    .catch(error => error);
  }

function* getCatalogsListFromRequest({payload}) {
  const {group} = payload;
  try {
    const catalogsList = yield call(getCatalogsRequest, group);
    if (catalogsList.message) {
      yield put(showCatalogsMessage(catalogsList.Message));
    } else {
      yield put(getCatalogsSuccess(catalogsList.catalogsList))
    }
  } catch (error) {
    yield put(showCatalogsMessage(error));
  }
}

export function* getCatalogsList() {
  yield takeEvery(GET_CATALOGS, getCatalogsListFromRequest);
}

export default function* rootSaga() {
  yield all([
    fork(getCatalogsList)
  ]);
}

这是通过Axios执行ajax请求的文件(我确定永远不会到达此代码,也永远不会执行对后端服务器的请求):

import axios from 'axios';
import {backendServer} from './constants';

const getCatalogsEndpoint = backendServer + 'api/util/catalogs/';

const getCatalogs = (group) => {
  console.log('here inside getCatalogs in backend/Catalogs');
  return axios.get(getCatalogsEndpoint+(group=null)?null:'?group='+group)
  .then(Response => {
    return {catalogsList: Response.data}
  })
  .catch(Error => Error);
};

export const catalogs = {
  getCatalogs: getCatalogs
}

CatalogsHeader.js中出现问题,因为this.props.catalogsList的值始终为undefinedenter image description here

1 个答案:

答案 0 :(得分:0)

我在 CatalogHeader 中看到了问题。我想,你指的是错误的流行音乐。

在 index.js 中,您将道具作为 catalogsList={catalogsList} 传递给 CatalogHeader。

但是在 CatalogHeader 中,您以 const {catalogs} = this.props; 的形式访问 prop,即未定义的目录。请尝试将其更改为 catalogsList。