#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]);
Дайте мне знать, если это сработает для вас, если нет, пожалуйста, прокомментируйте, что нужно улучшить, я соответствующим образом скорректирую свой ответ.