(错误)使用 React-Redux mapStateToProps + Reducers 将数据从一个组件传递到另一个组件

(Error) Passing data from one component to another using React-Redux mapStateToProps + Reducers

在花费数小时尝试将数据从一个组件传递到另一个组件的各种方法后,我完全不知道为什么下面的代码不起作用。

目的:我只是想在单击“NavLink”按钮期间将“courseID”(一个字符串)传递给应用程序的状态;使 Navlink 打开的组件能够通过状态读取此字符串。

根据 console.log 消息,“selectedCourseAction.js”似乎是用正确的 courseID 值触发的,但 selectedCourseReducer 始终显示初始值,实际上并未更新。

CourseDetails.js

import React from 'react';
import { connect } from 'react-redux';
import { firestoreConnect } from 'react-redux-firebase';
import { compose } from 'redux';
import { NavLink } from 'react-router-dom'; //Use NavLink rather than Link to gain access to the "active" class when the link is pressed.
import { selectedCourseID } from '../../store/actions/selectedCourseActions'


const CourseDetails = (props) => {


    const { ChosenCourse, removeCourse} = props;


    (...)

        console.log(props.match.params.id); <--------- Displays the currently selected Course Id.

        return(

            <div>

               (...)
                 
               //On NavLink click below, the idea is to pass the "course Id" of this component (displayed in 'props.match.params.id') into the "createLecture" component which the NavLink is trying to open via the "selectedCourseID" function found in "selectedCourseActions.js"
           
      <NavLink onClick={ () => selectedCourseID(props.match.params.id)} to={'/createlecture'} 
      className='btn btn-floating custom-orange lighten-1'>New Lecture</NavLink>

               (...)

        )

}

const mapStateToProps = (state, ownProps) => {

    const courseId = ownProps.match.params.id;

    console.log(courseId);   <------------------ Displays the currently selected Course Id.

     (...)
    
  
    return {
        selectedCourseID: courseId,   <------------This appears to trigger the selectedCourseAction.js
        (...)
        
    }

}

const mapDispatchToProps = (dispatch) => {

 (...)

}




export default compose(connect(mapStateToProps, mapDispatchToProps), firestoreConnect([
    {   
        (...)

    }
    
])
)(CourseDetails)

selectedCourseActions.js

export const selectedCourseID = (CourseId) => {

    console.log('Inside SelectedCourseActions.js: ' + CourseId); <------- This is triggered when the NavLink in the "CourseDetails.js" component is clicked and this displays the CourseId.
    return {

        type: 'UPDATE_SELECTED_COURSE_ID', <--------- This leads to selectedCourseReducer.js
        SelectedCourseID: CourseId          <--------- Intending to pass this SelectedCourseID value into the selectedCourseReducer.js, to save its value in the state of the application for later retrieval.

    }
    
};

selectedCourseReducer.js


const initState = 'Initial State of SelectedCourseReducer'; <---- Just temporary string to indicate if the initialState of the reducer is ever changed.


const selectedCourseReducer = (state=initState, action) => {
    


    switch (action.type) {
        
        case 'UPDATE_SELECTED_COURSE_ID':
            console.log('Updating Selected Course ID inside selectedCourseReducer: ', action.selectedCourseID); <------- THIS IS NEVER REACHED.  The default below is always called.
            return action.selectedCourseID;  <------- Trying to return the updated selectedCourseID value onto the state of the application.

        default:
            console.log('Hit Default State inside selectedCourseReducer: ', action.selectedCourseID); <----- THIS IS ALWAYS REACHED when this reducer is called with the "action.selectedCourseID" of "undefined".
            return state;
           
    }
    
}


export default selectedCourseReducer

对于未来的观众,这里是解决方案(灵感来自 markerikson 的回应)

需要在“CourseDetails.js”组件的mapDispatchToProps中引入selectedCourseID。 (请参阅下面的一些 steps/code)

导入 useDispatch()

import { useDispatch } from 'react-redux';

引入 selectedCourseID 和 dispatch = useDispatch();

(...) 

const { ChosenCourse, removeCourse, selectedCourseID} = props;
    const dispatch = useDispatch();

(...)

更改 NavLink 以引用调度

<NavLink onClick={ () => dispatch(selectedCourseID(props.match.params.id))} to={'/createlecture'} ... 

在 mapDispatchToProps 中添加调度

const mapDispatchToProps = (dispatch) => {

    return {
        (...) 
        selectedCourseID: (courseId) => dispatch(selectedCourseID(courseId)),
    }

}
export default compose(connect(mapStateToProps, mapDispatchToProps), firestoreConnect([
    {   
        (...)

    }
    
])
)(CourseDetails)

因为您没有调度一个动作。您正在调用 selectedCourseID 动作创建器,但该动作从未传递给 store.dispatch:

 onClick={ () => selectedCourseID(props.match.params.id)}

您应该通过 mapDispatch 参数传递 selectedCourseID 动作创建者,最好使用 the "object shorthand" form of mapDispatch:

const mapDispatch = {selectedCourseID};

// later
export default connect(mapState, mapDispatch)(MyComponent);

然后以 props.selectedCourseID 的形式访问它,无论是按字面上的方式还是通过解构:

const { ChosenCourse, removeCourse, selectedCourseID } = props;

或者,考虑使用 the React-Redux hooks API 而不是 connect,此时我们通常推荐:

const CourseDetails = (props) => {
  const dispatch = useDispatch();

  // later

  return <NavLink onClick={ () => dispatch(selectedCourseID(props.match.params.id))} />
}