javascript - 在这种情况下,如何正确地从 reducer /操作中调用函数?

标签 javascript redux react-redux material-ui

我尝试调用的操作/ reducer 不起作用。它似乎并没有真正按照我调用它的方式读取该函数。问题出在deleteWorkout函数中。

我尝试过使用mapDispatchToProps,并且尝试直接从操作中调用操作。 src-index.js

import React from 'react';
import { createStore } from 'redux';
import allReducer from './reducers';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom';
import throttle from 'lodash/throttle';
// import registerServiceWorker from './registerServiceWorker';
import App from './App';
import { loadState, saveState } from './localStorage';

const persistedState = loadState();

const store = createStore(
    allReducer,
    persistedState,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

store.subscribe(throttle(() => {
    saveState({
        workoutList: store.getState().workoutList
    });
}, 100));

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, 
    document.getElementById('root')
);
// registerServiceWorker();

reducer -index.js

import { combineReducers } from 'redux'
import switchLogin from './SwitchLogin'
import workoutList from './WorkoutList'
import { reducer as AddWorkout } from 'redux-form'

const allReducers = combineReducers({
    switchLogin,
    workoutList,
    form: AddWorkout,
})

export default allReducers;

WorkoutItem 类

import React, { Component } from "react";

import ExpansionPanel from "@material-ui/core/ExpansionPanel";
import ExpansionPanelSummary from "@material-ui/core/ExpansionPanelSummary";
import ExpansionPanelDetails from "@material-ui/core/ExpansionPanelDetails";
import ExpansionPanelActions from "@material-ui/core/ExpansionPanelActions";

import TableHead from "@material-ui/core/TableHead";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableRow from "@material-ui/core/TableRow";
import Table from "@material-ui/core/Table";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
// import { MuiThemeProvider } from "material-ui/styles";

import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
import ExerciseList from "./ExerciseList";

// import EditWorkoutItem from "./EditWorkoutItem";
import * as workoutActionCreators from '../../actions';
import { bindActionCreators } from 'redux';
import { connect } from "react-redux";

import moment from "moment";

export default class WorkoutItem extends Component {
  state = {
    open: false
  };

  handleSelectedPanel = () => {
    this.props.onSelectedPanel(this.props.workout.id);
  };

  // Opens the page
  handleClickOpen = () => {
    this.setState({ open: true });
  };

  // Cancels the changes and closes the page
  handleClose = () => {
    this.setState({ open: false });
  };

  deleteWorkout = id => {
    console.log(this);
    this.setState({ open: false });
    this.props.removeWorkout(id);
  };

  render() {
    const { workout } = this.props;
    const { id, name, duration, exerciselist } = workout;
    const date = moment(workout.date).format("L");

    return (
      <ExpansionPanel style={styles.panel} id={id} onChange={this.handleSelectedPanel}>
        <ExpansionPanelSummary>
          <Typography variant="button" style={styles.header}>
            {name}
          </Typography>
          <Typography variant="button" style={styles.header}>
            {date}
          </Typography>
          <Typography align="right" style={styles.header}>
            ~{duration} mins
          </Typography>
        </ExpansionPanelSummary>
        <ExpansionPanelDetails>
          <Table size="medium" style={styles.table}>
            <TableHead>
              <TableRow>
                <TableCell padding="none">Name</TableCell>
                <TableCell padding="none" align="right">
                  # of sets
                </TableCell>
                <TableCell padding="none" align="right">
                  average reps
                </TableCell>
                <TableCell padding="none" align="right">
                  weight
                </TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {exerciselist.map(exercise => (
                <ExerciseList key={exercise.id} exercise={exercise} />
              ))}
            </TableBody>
          </Table>
          <ExpansionPanelActions disableSpacing style={styles.actionButton}>
            {/* <MuiThemeProvider>
              <EditWorkoutItem id={id} />
            </MuiThemeProvider> */}
            <>
              <Button size="small" disableRipple onClick={this.handleClickOpen}>
                Remove
              </Button>
              <Dialog
                open={this.state.open}
                onClose={this.handleClose}
                aria-labelledby="alert-dialog-title"
                aria-describedby="alert-dialog-description"
              >
                <DialogTitle id="alert-dialog-title">
                  {"Are you sure?"}
                </DialogTitle>
                <DialogContent>
                  <DialogContentText id="alert-dialog-description">
                    This will permanently remove the workout. This action cannot
                    be undone.
                  </DialogContentText>
                </DialogContent>
                <DialogActions>
                  <Button onClick={this.handleClose} color="primary">
                    Cancel
                  </Button>
                  <Button
                    onClick={() => this.deleteWorkout(id)}
                    color="primary"
                    autoFocus
                  >
                    Yes, Remove It
                  </Button>
                </DialogActions>
              </Dialog>
            </>
          </ExpansionPanelActions>
        </ExpansionPanelDetails>
      </ExpansionPanel>
    );
  }
}

const mapDispatchToProps = dispatch => {
  return { ...bindActionCreators(workoutActionCreators, dispatch) };
};

connect(
  null,
  mapDispatchToProps
)(WorkoutItem);

行动:

export const removeWorkout = id => ({ type: 'REMOVE_WORKOUT', id })

reducer :

        case 'REMOVE_WORKOUT':
            console.log(action.id)
            return state = {
                ...state,
                workoutlist: state.workoutlist.filter((workout) => workout.id !== action.id)
        }

没有错误消息。但当我使用 console.log 时它返回正确的 id 并且它确实关闭了文本框。这就是我知道它停在函数处的方式

最佳答案

第一个主要问题是您没有调用正确的“调度程序”函数,而是调用原始函数。

将您的deleteWorkout更改为:

deleteWorkout = id => {
    console.log(id);
    this.setState({ open: false });
    this.props.removeWorkout(id);
  };

第二个主要问题是,您没有导出已连接的 Redux 容器,而是导出尚未连接到 Redux 的 React 组件。

从类声明中删除“导出默认值”:

class WorkoutItem extends Component {
// ...

并将其添加到 Redux 容器中:

export default connect(
    null,
    mapDispatchToProps
)(WorkoutItem);

编辑(这是实现bindActorCreators函数思想的可选更改。bindActorCreators也可以将单个 Action 创建者作为第一个参数)。 而且您似乎将单个 Action 创建者作为第一个参数传递给 redux 函数 bindActionCreators,但该函数采用 Action 创建者的映射。 https://redux.js.org/api/bindactioncreators

您有两种解决方法:

  1. 不要使用bindActionCreators(如果你是redux初学者更好)
const mapDispatchToProps = dispatch => {
  return { removeWorkout: (id) => dispatch(removeWorkout(id)) };
};
  • 正确使用bindActionCreators
  • // you need to import your action crerators in single object
    import * as workoutActionCreators from 'path_to_your_action_creators';
    
    // ...
    
    // bind all action creators with dispatch function and the bound action creators map to props
    const mapDispatchToProps = dispatch => {
      return { ...bindActionCreators(workoutActionCreators, dispatch) };
    };
    
    

    关于javascript - 在这种情况下,如何正确地从 reducer /操作中调用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57898408/

    相关文章:

    javascript - Google maps API v3,无法点击标记

    javascript - 如何从 DOM 中删除 sibling ?

    javascript - Backbone 尝试使用 put 而不是 post

    javascript - Kendo UI Grid 处理列模板中的缺失值

    javascript - 发送来自 reducer 的数据之前调用 action creator 的组件

    react-native - 如何重新渲染一些组件而不是全部?

    javascript - 使用 Immutable js 合并对象

    javascript - 单元测试 Redux 操作 - Thunk Undefined

    javascript - 我无法使用带有 react.js 的 redux 从 github api 获得响应

    react-redux - Jest mocking - 模拟命名导出,除了一个