Похоже, не удается передать реквизит от компонента к компоненту. (Реакция/Исправление)

#reactjs #redux #react-redux

Вопрос:

У меня возникла проблема, из-за которой я получаю неопределенную ошибку каждый раз, когда передаю опору от одного компонента к другому. У меня есть два компонента, в которых я пытаюсь передать опору от родительского компонента к дочернему. Компонент моего приложения выполняет действие Redux под названием getSession (), чтобы получить данные сеанса из нашего основного приложения с помощью вызова api для использования в этом приложении react. Для этого я использую функцию 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». С помощью этого идентификатора контакта я вызываю другое действие под названием getCoursework() в useEffect() этого компонента для выполнения курсовой работы конкретного студента. Проблема, с которой я сталкиваюсь, заключается в том, что, когда я передаю идентификатор контакта в качестве реквизита, я получаю идентификатор контакта, установленный как неопределенный.

 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;
 

Комментарии:

1. Можете ли вы попробовать ввести идентификатор контакта внутри if(contactID != null) блока в свой эффект использования? Есть ли у него там значение, соответствующее значению, которое вы от него ожидали? Также, пожалуйста, подтвердите, что console.log("CONTACT ID: " sessionCId); в вашем App.js не отображается неопределенное значение для sessionCId .

2. Я проверил cessionCId, и эта переменная отображает значение идентификатора контакта на втором рендере, который я считаю. Сейчас я проверю условность.

3. Да @KevinHaxhi. Я считаю, что эффект использования заключается в игнорировании условного. Я извлек из него отправку, чтобы проверить ведение журнала, если идентификатор контакта не равен нулю и в журналах chrome ничего не отображается.

Ответ №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]);
 

Дайте мне знать, если это сработает для вас, если нет, пожалуйста, прокомментируйте, что нужно улучшить, я соответствующим образом скорректирую свой ответ.