首页 > 解决方案 > React/TypeScript/Redux/Thunk 动作未分派且状态未更新

问题描述

我正在尝试使用 React-Redux 和 TypeScript 向 API 发出 GET 请求,方法是尝试在我单击按钮(onClick 事件)时分派发出请求的操作,然后我想使用减速器然后控制台更新状态.log 更新的状态,但是我似乎只能让商店中的初始化状态出现在控制台中,我不太确定出了什么问题,但似乎我的操作甚至没有发送到我的reducer(我的操作中的 console.log 没有被触发,它也没有出现在我的 reducer switch 语句中),这里是我的逻辑错误所在的文件:

编辑:动作被触发,我在下面写的console.log //EDIT 出现在控制台中,但由于某种原因它没有被发送到我的reducer ...

src/actions/movieActions.ts:

import { ActionCreator, Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { IMovieState } from '../reducers/movieReducer';
import axios from 'axios';

export enum MovieActionTypes {
    ANY = 'ANY',
    GENRE = 'GENRE',
}

export interface IMovieGenreAction {
    type: MovieActionTypes.GENRE;
    property: Array<String>;
}

export type MovieActions = IMovieGenreAction;

/*<Promise<Return Type>, State Interface, Type of Param, Type of Action> */
export const movieAction: ActionCreator<ThunkAction<Promise<any>, IMovieState, any, IMovieGenreAction>> = () => {
  //EDIT
  console.log('movieAction Triggered')
  return async (dispatch: Dispatch) => {
    try {
      dispatch({
        type: MovieActionTypes.GENRE
      })
      console.log('moveActions called')
      const res = await axios.get(`https://api.themoviedb.org/3/genre/movie/list?api_key=${process.env.REACT_APP_MOVIE_API_KEY}&language=en-US`)
      dispatch({
        property: res,
        type: MovieActionTypes.GENRE
    })
  } catch (err) {
    console.log(err);
  }
} 
};

src/reducers/movieReducer.ts:

import { Reducer } from 'redux';
import { MovieActionTypes, MovieActions } from '../actions/movieActions';

export interface IMovieState {
    property: any;
    genres: any;
}

const initialMovieState: IMovieState = {
    property: null,
    genres: 'askksakd'
};

export const movieReducer: Reducer<IMovieState, MovieActions> = (
    state = initialMovieState,
    action
    ) => {
      switch (action.type) {
        case MovieActionTypes.GENRE: {
          console.log('MOVE ACTION CALLED')
          return {
            ...state,
            genres: action.property
          };
        }
        default:
          console.log('default action called')
          return state;
      }
  };

src/store/store.ts:

import { applyMiddleware, combineReducers, createStore, Store } from 'redux';
import thunk from 'redux-thunk';
import { IMovieState, movieReducer } from '../reducers/movieReducer';

// Create an interface for the application state
export interface IAppState {
  movieState: IMovieState
}

// Create the root reducer
const rootReducer = combineReducers<IAppState>({
  movieState: movieReducer
});

// Create a configure store function of type `IAppState`
export default function configureStore(): Store<IAppState, any> {
  const store = createStore(rootReducer, undefined, applyMiddleware(thunk));
  return store;
}

src/components/MovieForm.tsx(应该发送动作的文件):

import React, { useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Box from '@material-ui/core/Box';
import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem';
import { spacing } from '@material-ui/system';
import Card from '@material-ui/core/Card';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import { CardHeader, TextField, CircularProgress } from '@material-ui/core';
import { useDispatch, useSelector } from 'react-redux';
import { movieAction } from '../actions/movieActions';
import { IAppState } from '../store/store';
import axios from 'axios';


const MovieForm = () => {

  const dispatch = useDispatch()
  const getGenres = () => {
    console.log('actions dispatched')
    dispatch(movieAction)
  }

  const genres = useSelector((state: IAppState) => state.movieState.genres);

  //const [genreChoice, setGenreChoice] = useState('')

  return (
    <>
    <h1>Movie Suggester</h1>
    <Paper elevation={3}>
      <Box p={10}>
        <Card>
          <div>Hello World. </div>
          <Select onChange={() => console.log(genres)}>
            <MenuItem>
              meow
            </MenuItem>
            <br />
            <br />
          </Select>
          <Button onClick={() => {
            getGenres()
            setTimeout(function(){
              console.log(genres)
            }, 5000)
          }}>genres list</Button>
          <Button onClick={() => console.log(axios.get(`https://api.themoviedb.org/3/discover/movie?api_key=${process.env.REACT_APP_MOVIE_API_KEY}&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&with_genres=35&page=1`))}>Click me</Button>
        </Card>
      </Box>
    </Paper>
    </>
  )
}


export default MovieForm

这是 src/index.tsx 以防问题在这里,我不知道:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import { BrowserRouter as Router } from 'react-router-dom';
import './index.css';
import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/core/styles';
import theme from './theme';
import App from './App';
import configureStore from './store/store';

const store = configureStore();

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <ThemeProvider theme={theme}>
      {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
      <CssBaseline />
        <Router>
          <App />
        </Router>
      </ThemeProvider>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

感谢您查看此内容并尝试帮助我了解我无法做到的事情!

标签: reactjstypescriptreduxredux-thunkstate-management

解决方案


这样做dispatch(movieAction())是因为 movieAction 是一个创建动作的函数,因此您需要调用它并调度生成的动作。


推荐阅读