【问题标题】:Can't seem to pass prop from component to component. (React/Redux)似乎无法将道具从组件传递到组件。 (反应/Redux)
【发布时间】:2021-10-07 07:09:51
【问题描述】:

我遇到了一个问题,每次我将道具从一个组件传递到另一个组件时都会收到未定义的错误。我有两个组件,我试图将道具从父组件传递给子组件。我的 App 组件正在执行一个名为 getSession() 的 Redux 操作,以通过 api 调用从我们的主应用程序中获取会话数据,以便在此反应应用程序中使用。我正在使用 componentDidMount 函数来执行此操作。

import './App.css';
import React, {Component} from 'react';
import QuickClassifyHeader from './components/Header';
import StudentCourseTable from './components/StudentCourseTable';
import CourseSearch from './components/CourseSearch';
import CourseApproval from './components/CourseApproval';
import {BrowserRouter,Route, Switch} from "react-router-dom";
import { Layout, Drawer, Button } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import { connect } from 'react-redux';
import { getSession } from './components/redux/actions/sessionActions';



const { Content } = Layout;

class App extends Component{
    
  state = {
      visible: false,
    }

    //initialize props when this component turns on
    // constructor(props){
    //   super(props);
    // }

    componentDidMount()
    {
      //call get session action
      this.props.getSession();
    }

    showDrawer = () => {
        this.setState({
            visible: true,
        });
    }

    onClose = () => {
        this.setState({
            visible: false,
        });
    }

    render()
    {

        const sessionCId = this.props.session["contactID"];
        console.log("CONTACT ID: " + sessionCId);
        return (
            <div className="App">   
            <BrowserRouter basename={'quickclassify/'}>
                <Switch>
                  <Route exact path="/" render={() =>
                        <Layout hasSider="true" >
                        <Content>
                            <Drawer
                              title="Course Search"
                              placement="left"
                              closable={true}
                              visible={this.state.visible}
                              onClose={this.onClose}
                              key="left"
                              width="40%">
                              <CourseSearch/>
                            </Drawer> 
                            <div style={{zIndex: '2', position: 'absolute', top: '10px', left: '10px'}}>
                              <Button
                                type="primary"
                                size="large"
                                shape="circle" 
                                onClick={this.showDrawer} 
                                icon={<SearchOutlined />}></Button>
                            </div>
                              <QuickClassifyHeader contactID={sessionCId}></QuickClassifyHeader>
                              <StudentCourseTable />
                        </Content>
                        </Layout>
                    }
                  />
                  <Route path="/quickclassify/course-approval" component={CourseApproval} />
                </Switch>    
              </BrowserRouter> 
          </div>
        )
    }
}

const mapStateToProps = state => ({
    session: state.session.item
});

export default connect(mapStateToProps, { getSession })(App);

获得会话后,我通过“contactID”道具将从该会话状态接收到的联系人 ID 传递给我的标头组件。使用该contactID,我在该组件的useEffect() 中调用另一个名为getCoursework() 的操作来提取特定学生的课程作业。我遇到的问题是,当我将contactID 作为道具传递时,我将contactID 设置为未定义。

import React, { useEffect } from "react";
import { Row, Col, Button, Input, Tag, Spin } from 'antd';
import { BrowserRouter, Link } from "react-router-dom";
import ReusableButton from './common/Button';
import eventBus from '../utils/eventBus';
import {Helmet} from "react-helmet";
import { UserOutlined } from '@ant-design/icons';
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { getCoursework } from './redux/actions/courseworkAction';






const QuickClassifyHeader = props => {

    //redux hooks to grab our coursework state and dispatch
    const coursework = useSelector(state => state.coursework.items);
    const dispatch = useDispatch();

    //contactID prop that was passed in from the App component
    const {contactID} = props;


    useEffect(() => {
        if(contactID != null)
        {
            //when component mounts on the screen
            dispatch(getCoursework(contactID));  
        }
        return() => {
            //when the component is unmounting...
            console.log("unmounting...")
        }
    }, []);

    let profile = new Object();
    profile = coursework['studentProfile'];
    console.log(JSON.stringify(profile));



  
    //TODO: Figure out what to do with these constants later
    const degree =  "";
    const program = "";
    const dob = "";
    const formerName = "";
    const name = "";
    const concentration = "";


    if(profile != null)
    {
        return ( 
            <div style={{backgroundColor: '#ffffff', borderBottom: 'solid 3px #88288A'}}>
                <Helmet>
                    <title>QuickClassify - Main Screen</title>
                    <link rel="icon" type="image/png" href="https://www.excelsior.edu/wp-content/uploads/2019/02/cropped-ec-favicon-32x32.png" sizes="32x32"/>
                </Helmet>
                <Row  style={{paddingTop: '10px'}}>
                    <Col span={2}></Col>
                    <Col span={10}>
                        <Input 
                            prefix={<UserOutlined />}
                            size="middle"
                            placeholder="Search for a Contact ID..." 
                            // onKeyPress={handleKeyPress}
                            value={props.contactID} 
                            />
                    </Col>
                    <Col span={12} style={{textAlign: 'right', paddingRight: '10px'}}>
                        <a style={{ marginRight: '20px'}}>Proofing SR</a>
                        <img src="https://sistest.int.excelsior.edu/sis/images/folder.gif" style={{ marginRight: '20px', marginBottom: '5px', height: '24px'}} />
                        <img src="https://sistest.int.excelsior.edu/sis/images/map2.gif" style={{height: '24px'}} />                    
                    </Col>
                </Row>
                <Row style={{padding: '10px 10px'}}>
                    <Col span={2} style={{textAlign: 'left'}}></Col>
                    <Col span={12} style={{textAlign: 'left'}}>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>Name</b> {profile.firstName}</Tag>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>Degree</b> {profile.svcProgramCode}</Tag>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>Concentration</b> {profile.concentrationCode}</Tag>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>Program</b> {profile.svcProgramCode}</Tag>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>DOB</b> {profile.dob}</Tag>
                        <Tag color="#88288A" style={{marginRight: '10px'}}><b>Former Names</b> {profile.formerNames}</Tag>
                    </Col>
                    <Col span={10} style={{textAlign: 'right'}}>
                        <Button 
                            style={{marginRight: '10px'}}
                            type="primary"
                            // onClick={handleSaveButtonClicked}
                            >
                            Save Changes
                        </Button>                   
                        <BrowserRouter>
                            <Link 
                            to="/course-approval"
                            target="_blank"
                            >
                            <ReusableButton 
                            colSize={3}  
                            btnName="Course Approval"
                            />       
                            </Link>
                        </BrowserRouter>
                    </Col>   
                </Row>
                <Spin 
                    size="large"
                    //TODO: Set up loading for this component later.
                    spinning={false} 
                    delay={500} 
                    style={{ position: 'absolute', 
                             top: '200px', 
                             left: '49%',
                             backgroundColor: '#ffffff', 
                             border: 'solid 3px #88288A',
                             padding: '50px 50px',
                             zIndex: '1001'
                            }} />
            </div>
         );
    }
    return ( 
        <div style={{backgroundColor: '#ffffff', borderBottom: 'solid 3px #88288A'}}>
            <Helmet>
                <title>QuickClassify - Main Screen</title>
                <link rel="icon" type="image/png" href="https://www.excelsior.edu/wp-content/uploads/2019/02/cropped-ec-favicon-32x32.png" sizes="32x32"/>
            </Helmet>
            <Row  style={{paddingTop: '10px'}}>
                <Col span={2}></Col>
                <Col span={10}>
                    <Input 
                        prefix={<UserOutlined />}
                        size="middle"
                        placeholder="Search for a Contact ID..." 
                        // onKeyPress={handleKeyPress}
                        value={props.contactID} 
                        />
                </Col>
                <Col span={12} style={{textAlign: 'right', paddingRight: '10px'}}>
                    <a style={{ marginRight: '20px'}}>Proofing SR</a>
                    <img src="https://sistest.int.excelsior.edu/sis/images/folder.gif" style={{ marginRight: '20px', marginBottom: '5px', height: '24px'}} />
                    <img src="https://sistest.int.excelsior.edu/sis/images/map2.gif" style={{height: '24px'}} />                    
                </Col>
            </Row>
            <Row style={{padding: '10px 10px'}}>
                <Col span={2} style={{textAlign: 'left'}}></Col>
                <Col span={12} style={{textAlign: 'left'}}>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>Name</b></Tag>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>Degree</b></Tag>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>Concentration</b></Tag>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>Program</b></Tag>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>DOB</b></Tag>
                    <Tag color="#88288A" style={{marginRight: '10px'}}><b>Former Names</b></Tag>
                </Col>
                <Col span={10} style={{textAlign: 'right'}}>
                    <Button 
                        style={{marginRight: '10px'}}
                        type="primary"
                        // onClick={handleSaveButtonClicked}
                        >
                        Save Changes
                    </Button>                   
                    <BrowserRouter>
                        <Link 
                        to="/course-approval"
                        target="_blank"
                        >
                        <ReusableButton 
                        colSize={3}  
                        btnName="Course Approval"
                        />       
                        </Link>
                    </BrowserRouter>
                </Col>   
            </Row>
            <Spin 
                size="large"
                //TODO: Set up loading for this component later.
                spinning={false} 
                delay={500} 
                style={{ position: 'absolute', 
                         top: '200px', 
                         left: '49%',
                         backgroundColor: '#ffffff', 
                         border: 'solid 3px #88288A',
                         padding: '50px 50px',
                         zIndex: '1001'
                        }} />
        </div>
     );
}
 
export default QuickClassifyHeader;

【问题讨论】:

  • 您可以尝试在您的 useEffect 中的if(contactID != null) 块内记录contactID 吗?它的价值是否与您期望的价值相匹配?另外,请确认App.js 中的console.log("CONTACT ID: " + sessionCId); 没有为sessionCId 显示未定义。
  • 我已经检查了 cessionCId 并且该变量在我相信的第二次渲染中显示了联系人 ID 值。我现在将检查条件。
  • 是的@KevinHaxhi。我相信 useEffect 忽略了条件。如果 contactID 不为 null 并且 chrome 中的日志上没有显示任何内容,我会从它中取出调度以测试日志记录。

标签: reactjs redux react-redux


【解决方案1】:

我相信您的问题在于您的useEffect。您正在测试一个依赖于contactID 的条件,但正如您所说,至少在第二次渲染之前contactID 将不可用。因此,您需要将其作为依赖项添加到 useEffect 钩子中,以便它检测 contactID 道具何时发生变化并重新测试条件:

useEffect(() => {
        if(contactID !== undefined)
        {
            //when component mounts on the screen
            dispatch(getCoursework(contactID));  
        }
        return() => {
            //when the component is unmounting...
            console.log("unmounting...")
        }
    }, [contactID]);

如果这对你有用,请告诉我,如果没有,请评论需要改进的地方,我会相应地调整我的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2021-11-13
    • 2019-07-29
    • 2017-01-31
    • 2021-07-04
    相关资源
    最近更新 更多