Как устранить ошибку undefined proptype с помощью react, redux и graphql - PullRequest
0 голосов
/ 06 августа 2020
• 1000 эта ошибка, особенно когда я пытаюсь вытащить идентификатор записи из URL-адреса (... / record /: recordId) с помощью match.params.recordId и отправить его в методы действия / редуктора.

Мой код включает операторы console.log, чтобы попытаться отследить значение опоры 'record' между компонентом, действием и редуктором, однако журналы никогда не вызываются. Это наводит меня на мысль, что компонент никогда не использует хук useEffect для вызова действия, но я не уверен.

MyRecord Component:

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)

Records Reducer File:

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         
        });
    }
}

Ответы [ 3 ]

0 голосов
/ 06 августа 2020

Попытаться проверить при использовании цепочки операций объекта

Проверить undefined перед его использованием

match?.params?.recordId

Таким образом, это предотвратит ошибку.

0 голосов
/ 06 августа 2020

Ответ: Проблема была в моем компоненте. В моем методе mapStateToProps была опечатка «... state.record», но должно было быть «... state.records» из-за имени набора действий. Вот почему 'запись' не была определена, а методы действия / записи даже не вызывались.

0 голосов
/ 06 августа 2020

у вас неправильный импорт для Proptype. это будет

import PropTypes from 'prop-types';

, а проверка будет:

MyRecord.propTypes = {
    getrecord: PropTypes.func.isRequired,
    thisRecord: PropTypes.object
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...