繁体   English   中英

React-redux:当它在功能组件中工作时,为什么我不能访问类组件中的状态属性?

[英]React-redux: Why can't I access state properties in a class component, when it works in a functional component?

我对 React 和 Redux 还是很陌生,所以我不知道当我尝试通过 props 访问类组件中的属性与通过函数组件中的参数访问它们时导致错误的原因。

行动

import { FETCH_TOPMOVIES_SUCCESS,FETCH_TOPMOVIES_FAILURE,SELECT_MOVIE} from "./movieTypes";
import axios from "axios";

export const fetchTopMoviesSuccess = movies => {
    return {
        type: FETCH_TOPMOVIES_SUCCESS,
        payload: movies
    }
}

export const fetchTopMoviesFailure = error => {
    return {
        type: FETCH_TOPMOVIES_FAILURE,
        payload: error
    }
}

export const selectMovie = (movie) => {
    console.log('selected movie: ' + movie.title)
    return{
        type: SELECT_MOVIE,
        payload: movie
    }
}

export const fetchTopMovies = () => {
    return (dispatch) => {
        axios.get(api)
        .then(response => {
            const movies = response.data.results
            dispatch(fetchTopMoviesSuccess(movies))
            console.log('this is the response result:')
            console.log(response.data.results)
        })
        .catch(error => {
            const errorMsg = error.message
            dispatch(fetchTopMoviesFailure(errorMsg))
            console.log('this is the errror message:')
            console.log(errorMsg)
        })
    }
}

减速机

import { FETCH_TOPMOVIES_FAILURE, FETCH_TOPMOVIES_SUCCESS, SELECT_MOVIE } from "./movieTypes"

const initialState = {
    selectedMovie: null,
    movies: [],
    error: ''
}

export const moviesReducer = (state = initialState, action) => {
    switch (action.type) {
        case FETCH_TOPMOVIES_SUCCESS:
            console.log('returned successful request')
            return {
                movies: action.payload,
                error: '',
                selectedMovie: null
            }
        case FETCH_TOPMOVIES_FAILURE:
            console.log('error when fetching from the api')
            return {
                ...state,
                movies: [],
                error: action.payload
            }
        default: return state
    }
}

export const selectedMovieReducer = (state = initialState, action) => {
    switch (action.type) {
        case SELECT_MOVIE:
            return {
                ...state,
                selectedMovie: action.payload
            }
        default: return state
    }
}
import { combineReducers } from "redux";
import { moviesReducer, selectedMovieReducer } from "./movie/movieReducer";


const rootReducer = combineReducers({
    movies: moviesReducer,
    selectedMovie: selectedMovieReducer
    
})

export default rootReducer

店铺

import { createStore, applyMiddleware } from "redux";
import thunk from 'redux-thunk'
import rootReducer from "./rootReducer";

const store = createStore(rootReducer, applyMiddleware(thunk))

export default store

应用程序

import React from 'react';
import './App.css';
import MovieList from './Components/MovieList';
import store from './redux/store'
import { Provider } from 'react-redux';
import NewMovieList from './Components/NewMovieList';

function App() {
  return (
    <Provider store={store}>
      <div className="App">
        <NewMovieList/>
        <MovieList/>
      </div>
    </Provider>
  );
}

export default App;

现在,功能组件NewMovieList可以按预期工作。 它显示电影列表并且没有错误。
它看起来像这样:

import React, { useEffect } from 'react';
import './MovieList.css';
import Movie from './Movie';
import { connect } from 'react-redux';
import { fetchTopMovies } from '../redux';

function NewMovieList({ movies, fetchTopMovies }) {
    useEffect(() => {
        fetchTopMovies()
    }, [])
    return movies.error ? (
        <h2>{movies.error}</h2>
    ) : (
        <div>
            <h2>Movies:</h2>
            <div className='container'>
                <div className='moviegroup'>
                    <ul>
                        {
                            movies && movies.movies && movies.movies.map(movie => <Movie key={movie.id} movie={movie}></Movie>)
                        }
                    </ul>
                </div>
            </div>
        </div>
    )
}

const mapStateToProps = state => {
    return {
        movies: state.movies
    }
}

const mapDispatchToProps = dispatch => {
    return {
        fetchTopMovies: () => dispatch(fetchTopMovies())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(NewMovieList)

但是,类组件MovieList不起作用。 我得到“Uncaught TypeError: this.props.movi​​es.map is not a function”并且之前已经得到了其他错误,比如“无法读取未定义的属性”等。
该组件如下所示:

import React, { Component } from 'react';
import './MovieList.css';
import Movie from './Movie';
import { connect } from 'react-redux';
import { fetchTopMovies } from '../redux';

class MovieList extends Component {

    componentDidMount() {
        console.log('component did mount')
        this.props.fetchTopMovies()
    }

    render() {
        console.log(this.props)
        console.log(this.props.movies)
        return (
            <div className='container'>
                <div className='moviegroup'>
                    <ul className='movies'>
                        {
                            this.props.movies.map(movie => <Movie key={movie.id} movie={movie}></Movie>)
                        }
                    </ul>
                </div>
            </div>
        )
    }

}

const mapStateToProps = state => {
    return {
        movies: state.movies
    }
}

const mapDispatchToProps = dispatch => {
    return {
        fetchTopMovies: () => dispatch(fetchTopMovies())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MovieList);

在我看来,类组件无法读取状态,即使我通过 mapDispatchToProps 连接它,但我不确定,也不知道如何让它工作。
我真的很想了解如何使用这两种类型的组件,有人可以帮忙吗?

您在两个不同组件之间的代码是不一样的。

他们都从 Redux 存储中获取state.movies 没关系。

对于 reducer, state.movies是一个类似于{ selectedMovie: null, movies: [], error: '' }的对象。 这意味着在组件中,您关心的数组是movies.movies

该函数组件检查movies && movies.movies && movies.movies.map 所以,它正确地访问了嵌套数组。 (顺便说一句, movies && movies.movies部分是不必要的,因为state.movies.movies始终是一个数组 - 你以这种方式初始化它!)。

但是,组件并没有这样做。 它只是在做props.movies.map() .... 除了props.movies是像{selectedMovie, movies, error}这样的对象 所以,你需要这样做this.props.movies.movies.map()

话虽如此,恐怕您正在编写的 Redux 代码风格已经过时了,在多个方面:

  • 你是“手写”的 Redux reducer 和 action creator
  • 您正在使用connect
  • 您正在使用类组件

今天,我们使用 Redux Toolkit 和 React-Redux hooks API 教授“现代 Redux”,这更易于学习和使用。 您正在编写的代码将运行,但它需要编写至少 4 倍的代码,并且会更加混乱。

我强烈建议阅读我们的官方 Redux 文档教程,这些教程将 Redux Toolkit 和 React-Redux 钩子作为标准方法进行教学:

https://redux.js.org/tutorials/index

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM