Как использовать свойства match в React js при использовании context api

Я создаю базовое приложение и использовал хуки context api, fetch, react для всех компонентов, кроме компонента context api, потому что я все еще учусь использовать хуки.

Я получил свои данные из бэкэнда, я хочу использовать один компонент для создания и обновления моих данных, моя основная проблема в том, что я не знаю, как использовать опору соответствия внутри провайдера contextApi, чтобы получить идентификатор для editform и singleItem с использованием параметров. Я создал функцию, которая вызывает singleItem, и передал ее компоненту формы, так что это может быть начальное значение в случае редактирования, но это не сработало. У меня ошибка Unhandled Rejection (TypeError): Cannot read property 'params' of undefined.

мой компонент api контекста

import React, { Component, createContext } from 'react'

export const ContactContext = createContext()

export class ContactContextProvider extends Component {

  state = {
    Contact : [],

    singleContact:{}

  }

  componentDidMount(){
    fetch('http://127.0.0.1:5000/Contact')
    .then(res=>res.json())
    .then(data=>{
      this.setState({
        Contact:data
      })
      
    })

    this.getSingleItem()
    
  }

  getSingleItem = async() => {
    const fetch_id = await fetch(`http://127.0.0.1:5000/Contact/${this.props.match.params.id}`)
    const data = await fetch_id.json()

    this.setState({singleContact:data})

  }

  createContact = (item) =>{
    const req = {
      method : 'POST',
      headers : {'Content-Type':'application/json'},
      body: JSON.stringify(item)
    }
    fetch('http://127.0.0.1:5000/Contact/add', req)
    .then(res=>res.json())
    .then(data=> data)
  }

  editContact = (item) => {
    const req = {
      method : 'POST',
      headers : {'Content-Type' : 'application/json'},
      body : JSON.stringify(item)
    }
    fetch(`http://127.0.0.1:5000/Contact/edit/${this.props.match.params.id}`)
    .then(res=>res.json())
    .then(data=>console.log(data))
  }
  
  deleteContact =  (_id) => {
    fetch(`http://127.0.0.1:5000/Contact/${_id}`, {method:'DELETE'})
    .then(res=>res.json())
    .then(data=>console.log(data))
   

    this.setState({
      Contact : [...this.state.Contact.filter(item => item._id !== _id)]
    })
  }

  

  render() {
    return (
      <ContactContext.Provider value={{...this.state, createContact:this.createContact, editContact:this.editContact, deleteContact:this.deleteContact}}>
        {this.props.children}
      </ContactContext.Provider>
    )
  }
}

export default ContactContextProvider

Это моя форма для создания и редактирования данных


import { Form, Button, Col} from 'react-bootstrap';
import React, {useState, useContext} from 'react'
import { ContactContext } from '../context/ContactContext';

function Contactform() {
  const {createContact, singleContact, editContact} = useContext(ContactContext)

  const [Contact, setContact] = useState({
    firstName: singleContact.firstName || '',
    lastName: singleContact.lastName || '',
    company: singleContact.company || '',
    phone: singleContact.phone || '',
    email: singleContact.email || '',
    note: singleContact.note || ''
  

  })
  
  const handleChange = (e) =>{
    setContact((prevState)=>({
      ...prevState,
      [e.target.name]:e.target.value
    }))
  }

  const handleSubmit = (e) =>{
    e.preventDefault()
    const item = {
      firstName: Contact.firstName,
      lastName: Contact.lastName,
      company: Contact.company,
      phone: Contact.phone,
      email: Contact.email,
      note: Contact.note
     
      
    }

    if(Contact===''){
      createContact(item)
    }
     else {
       editContact(item)
     }
  }
  
  return (
    
    <Form id='form' onSubmit={handleSubmit} >
      <Form.Row>
    <Form.Group as={Col} >
      <Form.Label>First Name</Form.Label>
      <Form.Control name='firstName' value={Contact.firstName} onChange={handleChange} type="text" placeholder="First Name" />
    </Form.Group>
    <Form.Group as={Col} >
      <Form.Label>Last Name</Form.Label>
      <Form.Control name='lastName' value={Contact.lastName} onChange={handleChange} type="text" placeholder="Last Name" />
    </Form.Group>
    </Form.Row>
    <Form.Row>
    <Form.Group as={Col} >
      <Form.Label>Company</Form.Label>
      <Form.Control name='company' value={Contact.company} onChange={handleChange} type="text" placeholder="Company" />
    </Form.Group>
    <Form.Group as={Col} >
      <Form.Label>Phone</Form.Label>
      <Form.Control name='phone' value={Contact.phone} onChange={handleChange} type="text" placeholder="Phone" />
    </Form.Group>
    </Form.Row>
    <Form.Row>
    <Form.Group as={Col} >
      <Form.Label>Email</Form.Label>
      <Form.Control name='email' type="email" value={Contact.email} placeholder=" email" onChange={handleChange} />
    </Form.Group>
   
    </Form.Row>
   
   
    <Form.Group >
      <Form.Label>Note</Form.Label>
      <Form.Control as="textarea" name='note' value={Contact.note} onChange={handleChange}  rows={3} placeholder='Note'/>
    </Form.Group>
    
    
    <Button  id='form_btn' variant="primary"  type="submit">
      Submit
    </Button>
  </Form>
    )

  
}

export default Contactform

person lovelyn marshall    schedule 05.11.2020    source источник
comment
Предоставьте краткие примеры кода с минимальным объемом кода, необходимым для воспроизведения вашей проблемы.   -  person Yoav Kadosh    schedule 05.11.2020
comment
Хорошо, не могли бы вы сказать мне, какие компоненты мне нужно предоставить? Я новичок в этом и учусь.   -  person lovelyn marshall    schedule 05.11.2020


Ответы (1)


Вы можете просто сделать это. Я предполагаю, что вы уже используете react-router. Вы можете просто использовать withRouter hoc. Он пройдет все опоры маршрутизатора.

// Ваш контекстный api-компонент

import React, { Component, createContext } from 'react'
import { withRouter } from "react-router";

export const ContactContext = createContext()

class ContactContextProvider extends Component {

  state = {
    Contact : [],

    singleContact:{}

  }

  componentDidMount(){
    fetch('http://127.0.0.1:5000/Contact')
    .then(res=>res.json())
    .then(data=>{
      this.setState({
        Contact:data
      })
      
    })

    this.getSingleItem()
    
  }

  getSingleItem = async() => {
    const fetch_id = await fetch(`http://127.0.0.1:5000/Contact/${this.props.match.params.id}`)
    const data = await fetch_id.json()

    this.setState({singleContact:data})

  }

  createContact = (item) =>{
    const req = {
      method : 'POST',
      headers : {'Content-Type':'application/json'},
      body: JSON.stringify(item)
    }
    fetch('http://127.0.0.1:5000/Contact/add', req)
    .then(res=>res.json())
    .then(data=> data)
  }

  editContact = (item) => {
    const req = {
      method : 'POST',
      headers : {'Content-Type' : 'application/json'},
      body : JSON.stringify(item)
    }
    fetch(`http://127.0.0.1:5000/Contact/edit/${this.props.match.params.id}`)
    .then(res=>res.json())
    .then(data=>console.log(data))
  }
  
  deleteContact =  (_id) => {
    fetch(`http://127.0.0.1:5000/Contact/${_id}`, {method:'DELETE'})
    .then(res=>res.json())
    .then(data=>console.log(data))
   

    this.setState({
      Contact : [...this.state.Contact.filter(item => item._id !== _id)]
    })
  }

  

  render() {
    return (
      <ContactContext.Provider value={{...this.state, createContact:this.createContact, editContact:this.editContact, deleteContact:this.deleteContact}}>
        {this.props.children}
      </ContactContext.Provider>
    )
  }
}

export default withRouter(ContactContextProvider)

person Shubham Verma    schedule 05.11.2020
comment
Привет, Верма. Я благодарен за помощь, я сделал именно то, что вы просили, который использует withRouter для более точного сопоставления маршрута, и я перестал получать сообщение `` Необработанное отклонение (TypeError): невозможно прочитать параметры свойства undefined ''. ошибка ``, но теперь проблема в том, что я получаю `` ContactContext.js: 31 GET 127.0.0.1:5000/Contact/undefined 400 (неверный запрос) `` и когда я console.log (this.match), они props.match находят путь '/', а params.id неопределенный, - person lovelyn marshall; 05.11.2020
comment
Проверьте, отправляете ли вы идентификатор параметров или нет? - person Shubham Verma; 06.11.2020
comment
Я отправляю идентификатор параметров - person lovelyn marshall; 06.11.2020
comment
Вы сказали, что console.log this.match, это будет this.props.match. Вы можете это проверить? - person Shubham Verma; 06.11.2020