reactjs - 如何使用 react、redux 和 graphql 解决“未定义的 proptype”错误
问题描述
我正在尝试学习如何使用 graphql 构建 React/Redux 应用程序,但在解决“未捕获的类型错误:无法读取未定义的属性“记录”错误时遇到问题。
当我尝试使用“match.params.recordId”从 url (.../record/:recordId) 中提取“record” ID 并将其发送到 action/reducer 方法时,我特别遇到了这个错误。
我的代码包含 console.log 语句,以尝试跟踪组件、操作和减速器之间的“记录”道具的值,但从不调用日志。这让我相信该组件从不使用“useEffect”挂钩来调用操作,但我不确定。
我的记录组件:
import React, {useState, useEffect} from 'react'
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getrecord } from '../../actions/records';
import { Container, Row, Col, Card, Button, Form, ListGroup, Jumbotron, Modal } from 'react-bootstrap';
const MyRecord = ({getrecord, match, recordID = {id: match.params.recordId}, thisRecord:{record, loading}}) => {
useEffect(() => {
getrecord(recordID);
}, [getrecord, recordID]);
const LogInfo = () =>{
console.log('record ID: ',match.params.id);
console.log('record: ', record);
}
LogInfo();
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
{record === null ? (
<h2>Loading...</h2>
) : (
<Container id='MyRecord'>
<Row>
<Jumbotron className='recordJumbotron'>
<h1>Record: {record.recordname} </h1>
<Row>
<Col>
<Button variant="primary" onClick={handleShow}>
Add an Item To Your Record
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email" />
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" />
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Col>
<Col>
<Button>Upload a Document</Button>
</Col>
</Row>
</Jumbotron>
</Row>
<Row className='recordItemList'>
<Card className='recordItemList'>
<Card.Header>Record Items</Card.Header>
<Card.Body>
<Card.Title>Special title treatment</Card.Title>
<ListGroup variant="flush">
<ListGroup.Item>Cras justo odio</ListGroup.Item>
<ListGroup.Item>Dapibus ac facilisis in</ListGroup.Item>
<ListGroup.Item>Morbi leo risus</ListGroup.Item>
<ListGroup.Item>Porta ac consectetur ac</ListGroup.Item>
</ListGroup>
</Card.Body>
</Card>
</Row>
</Container>
)}
</>
)
}
MyRecord.propTypes = {
getrecord: PropTypes.func.isRequired,
thisRecord: PropTypes.object
};
const mapStateToProps = state => ({
thisRecord: state.record
});
export default connect(mapStateToProps, {getrecord})(MyRecord)
记录减速器文件:
import {
CREATE_RECORD_SUCCESS,
CREATE_RECORD_FAIL,
LIST_RECORDS_BY_OWNER,
GET_RECORD_BY_OWNER,
GET_RECORDS_SUBSCRIPTION
} from '../actions/types';
const initialState = {
record: null,
records: [],
loading: true,
error: {}
};
export default function (state = initialState, action) {
const {type, payload} = action;
switch(type){
case CREATE_RECORD_SUCCESS:
return {
...state,
...payload,
//record:[payload, ...state.records],
loading: false
};
case GET_RECORD_BY_OWNER:
return {
...state,
record: payload,
loading: false
};
case LIST_RECORDS_BY_OWNER:
return {
...state,
records:payload,
loading: false
};
case GET_RECORDS_SUBSCRIPTION:
return {
...state,
records:[payload, ...state.records],
loading: false
};
case CREATE_RECORD_FAIL:
return {
...state,
error: payload,
loading: false
};
default:
return state;
}
}
记录行动:
//GET A RECORD
//GET A RECORD
export const getrecord = (recordID) => async dispatch => {
try {
console.log(' id: ', recordID);
const res = await API.graphql(graphqlOperation(getRecord, recordID))
console.log('record by id: ', res.data.getRecord);
dispatch({
type: GET_RECORD_BY_OWNER,
payload: res.data.getRecord
})
console.log('getrecord: ', res)
} catch (error) {
console.error(error);
dispatch({
type: CREATE_RECORD_FAIL
});
}
}
解决方案
使用对象操作链时尝试验证
使用前检查未定义
match?.params?.recordId
这样,它将防止错误。
推荐阅读
- java - 如何使用java将阿拉伯语数据存储在mysql数据库中?
- unicode - 在 Pycharm 中显示无效字符
- mongodb - mongodb聚合管道没有返回正确的结果并且速度很慢
- double - 从字符串转换为双精度的问题
- android - java.lang.NullPointerException:尝试调用虚拟方法'void android.widget.TextView.setText(java.lang.CharSequence)'
- macos - macOS Catalina AudioServerPlugIn 安装
- json - 如何从 json 文件生成类图或 UML
- windows - 将环境变量从命令行传递给纱线
- css - Angular2 - 为什么 :host 不会随着 Safari 中的内容垂直增长?
- date - Hive 中的日期和时区