I'm creating a basic app and i used context api, fetch, react hooks for all the component except the context api component because, i'm still learning to use hooks.
I fetched my data from the backend, i want to use one component for my create and update of my data, my major problem is that i don't know how to use the match prop inside the contextApi provider to get the id for editform and singleItem using params. I created a function that calls a singleItem and i passed it to my form component, so it can be the initial value in case of editing but it didn't work. I got an error Unhandled Rejection (TypeError): Cannot read property 'params' of undefined
.
my context api component
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
This is my form for creating and editing data
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
You can simply do this. I am assuming you are already using react-router
.
You can simply use withRouter
hoc. It will pass all router props.
//Your context api component
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)