How to sync state in react.js? - javascript

I am having difficulty updating my state and my component. After a button is pressed and I change the value of one of the props of the popup component. The value of the props is not updated. I believe that this is one of the side effects of using the setstate. I did some research and saw that there is a way to solve this problem using the useeffect hook but I am unable to receive the result. Here is my code below:
My goal is to get from the form having the prop of Data0 to have a prop of Data1, but the prop does not seem to be updating at all.
I am simulating clicking multiple objects and the result is an update in the value of fromData. Thus, app.js is my parent component. The child component is the popup, whose value should change to Bob and an actual date instead of just string values of the original name and original date.
import React, { useState, useEffect } from 'react';
import './App.css';
import FormDialog from './component/popup'
import Button from '#material-ui/core/Button';
function App() {
const Data0 = { name:'original name', date:'original date' }
const Data1 = { name:'Bob', date:'1939' }
const [formStatus, setformStatus] = React.useState(false);
const [formdata2, setformData2] = useState(Data0)
const [tempform, settempform] = useState(<FormDialog formStatus = {formStatus} handelForm={() => handelForm()} Data0={Data0}/>)
const handelForm = () => {
const tempform = <FormDialog formStatus = {formStatus} handelForm={() => handelForm()} Data0={Data1}/>
settempform(tempform);
};
useEffect(() => {
const tempform = <FormDialog formStatus = {formStatus} handelForm={() => handelForm()} Data0={Data1}/>
settempform(tempform);
setformStatus(!formStatus);
console.log('formdata2 EFFECT', formdata2)
settempform(tempform);
setformStatus(!formStatus);
setformStatus(!formStatus);
}, [formdata2]
);
return (
<div className="App">
<h1 align="center">React-App</h1>
<h4 align='center'>Render Custom Component in Material Table</h4>
<Button variant="outlined" color="primary" onClick={() => handelForm()}>
Vendor row
</Button>
{tempform}
{formdata2.billingVendor}
</div>
);
}
export default App;
export default function FormDialog (props) {
let [Data, setData] = React.useState(props.Data0);
return (
<React.Fragment>
<Dialog
maxWidth='lg'
open={props.formStatus}
aria-labelledby="max-width-dialog-title"
disableBackdropClick= {true}
disableEscapeKeyDown={true}
>
<DialogTitle className={classes.title}>{Data.name}</DialogTitle>
<Divider />
<DialogContent>
<DialogContentText>
Please be cautious when updating the fields below.
</DialogContentText>
<form noValidate>
<FormControl className={classes.formControl} fullWidth= {true}>
<div className={classes.root}>
<TextField
fullWidth
label='Date'
style={{ margin: 8 }}
disabled
value={Data.name}
variant="outlined"
/>
<br/>
<TextField
fullWidth
label='Date'
style={{ margin: 8 }}
disabled
value={Data.name}
variant="outlined"
/>
<br/>
<TextField
fullWidth
style={{ margin: 8 }}
disabled
value={Data.date}
variant="outlined"
/>
<br/>
<TextField
fullWidth
style={{ margin: 8 }}
disabled
value={Data.date}
variant="outlined"
/>
<br/>
</div>
</FormControl>
</form>
</DialogContent>
<DialogActions>
<Button onClick={() => props.handelForm()} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
</React.Fragment>
);
}```

I think the process you are following is not a good one. You shouldn't store a react component in the state rather you should dynamically load the component or pass what prop you need.
import React, { useState, useEffect } from 'react';
import './App.css';
import FormDialog from './component/popup'
import Button from '#material-ui/core/Button';
function App() {
const Data0 = { name:'original name', date:'original date' }
const Data1 = { name:'Bob', date:'1939' }
const [formStatus, setformStatus] = React.useState(false);
const [formdata2, setformData2] = useState(Data0)
const [formData, setFormData] = useState(Data0)
const handelForm = () => {
// here change the state however you want
setFormData(Data0);
};
return (
<div className="App">
<h1 align="center">React-App</h1>
<h4 align='center'>Render Custom Component in Material Table</h4>
<Button variant="outlined" color="primary" onClick={() => handelForm()}>
Vendor row
</Button>
<FormDialog formStatus = {formStatus} handelForm={() => handelForm()} Data0={formData}/>
</div>
);
}
export default App;
In the FormDialog add the useEffect to perform the change
useEffect(() => {
setData(props.Data0)
}, [props.Data0])
This is update the state with the changes

You are creating a new state based on the value of the props in your child component, which is independent to the state in the parent component. So a change in the child cannot be passed back to the parent.
To fix it,
create the state in your parent component by
const [Data0, setData0] = useState({ name:'original name', date:'original date' })
pass the setState function to change the value in the parent component to your children by
const tempform = <FormDialog formStatus = {formStatus} handelForm={() => handelForm()} Data={Data1} setData={setData0}/>
change the value in your child component accordingly
let {Data, setData} = props;
Then the call of setData should be calling the one in your parent component and it should be able to update the value accordingly.

Related

How to clear a material-ui search input using a button

Working on a tutorial atm that involves react material-ui tables that also has a search input textfield. What I am trying to add to it, is a button that will reset the table report but also clear the search input textfield.
It is the clearing of the search textfield that I am having trouble with.
They are using this code as a separate component library called Controls.input:
import React from 'react'
import { TextField } from '#material-ui/core';
export default function Input(props) {
const { name, label, value,error=null, onChange, ...other } = props;
return (
<TextField
variant="outlined"
label={label}
name={name}
value={value}
onChange={onChange}
{...other}
{...(error && {error:true,helperText:error})}
/>
)
}
The main search code is as follows where I have also added a button
<Controls.Input
id="name"
label="Search Name"
className={classes.searchInput}
InputProps={{
startAdornment: (<InputAdornment position="start">
<Search />
</InputAdornment>)
}}
onChange={handleSearch}
/>
<Button
onClick={handleClear}
className="materialBtn"
>
Clear
</Button>
At this point, I am not sure how to reference/target the search input field as part of the handleClear function, in-order to clear it's contents?
const handleClear = () => {
????
}
Do I need to use useState()?
You are right with having to put the value into state. Based on what you have supplied it seems that your state needs to be in your parent component. So something like this should work
import { useState } from 'react'
const ParentComponent = () => {
const [value, setValue] = useState('')
const handleClear = () => {
setValue('')
}
const handleSearch = (event) => {
setValue(event.target.value)
}
return (
<>
<Controls.Input
id="name"
label="Search Name"
className={classes.searchInput}
value={value}
onChange={handleSearch}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
}}
/>
<Button onClick={handleClear} className="materialBtn">
Clear
</Button>
</>
)
}

when i click on update button i want the course open in add course with the same values

following is the AddCourse page
AddCourse.js
import React, { useEffect, useState } from 'react';
import { Button, Form, FormGroup, Label, Input, FormText, Container } from 'reactstrap';
import database from '../services/fire';
import { useSelector, useDispatch } from 'react-redux';
import uuid from 'react-uuid';
import '../App.css';
const AddCourse = () => {
const [courseId, setCourseId] = useState('');
const [courseTitle, setCourseTitle] = useState('');
const [courseDesc, setCourseDesc] = useState('');
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user.uid);
useEffect(() => {
document.title = "Add Courses"
}, [])
const addCourse = () => {
const payload = { id: uuid(), courseId:courseId, courseTitle: courseTitle, courseDesc: courseDesc }
const dbcoursesWrapper = database.ref().child(user).child('courses');
// const dbcoursesWrapper = database.ref(`users/${user}/courses`).push(courseId, courseTitle, setCourseDesc);
return dbcoursesWrapper.child(payload.id).update(payload).then(() => {
setCourseId('');
setCourseTitle('');
setCourseDesc('');
dispatch({ type: "ADD_COURSES", payload });
})
}
return (
<div>
<h1 className="text-center my-3">Fill Course Detail</h1>
<Form onSubmit={(e) => {
e.preventDefault(e.target.value);
addCourse();
}}>
<FormGroup>
<label for="UserId">Course Id</label>
<Input
type="text"
value={courseId}
onChange={(e) => setCourseId(e.target.value)}
placeholder="Enter your Id"
name="userId"
id="UserId"
/>
</FormGroup>
<FormGroup>
<label for="title">Course Title</label>
<Input
type="text"
value={courseTitle}
onChange={(e)=> setCourseTitle(e.target.value)}
placeholder="Enter Course Title"
name="title"
id="title"
/>
</FormGroup>
<label for="description">Course Description</label>
<Input
value={courseDesc}
onChange={(e) => setCourseDesc(e.target.value)}
type="textarea"
placeholder="Enter Course Description"
name="description"
id="description"
style={{ height: 150 }}
/>
<Container className="text-center">
<Button color="success" type='submit'>Add Course</Button>
<Button color="warning ml-3">clear</Button>
</Container>
</Form>
</div>
);
};
export default AddCourse;
courses.js here is the update button when i click on it i want it to open the AddCourse page with the same values of the course i want to update not getting any clue how can i do this
import React from 'react';
import {
Card, CardText, CardBody,
CardTitle, Button, Container
} from 'reactstrap';
import database from '../services/fire';
import { useSelector, useDispatch } from 'react-redux';
import { fetchCourse } from '../actions/courses';
import AddCourse from './AddCourse';
const Course = ({course}) => {
const user = useSelector(state => state.auth.user.uid);
const dispatch = useDispatch();
const removeCourse = (id) => {
console.log(id);
const dbtasksWrapper = database.ref().child(user).child('courses');
dbtasksWrapper.child(id).remove().then(() => {
dispatch({ type: 'DELETE_COURSE', id: id })
dispatch(fetchCourse(user));
})
}
return (
<div>
<Card>
<CardBody className="text-center ">
<CardText className="text-center"><h2>CourseID: {course.courseId}</h2></CardText>
<CardTitle className="font-weight-bold text-center"><h1>{course.courseTitle}</h1></CardTitle>
<CardText className="text-center">{course.courseDesc}.</CardText>
<Container className="text-center">
{/* here is the update button and when onclick its goes to add course page with the course vale need to update** */}
<Button color="warning"onClick={}>Update</Button>
<Button color="danger ml-4" onClick={()=>removeCourse(course.id)}>Delete</Button>
</Container>
</CardBody>
</Card>
</div>
);
};
export default Course;
Sorry, not getting your question properly. You are trying to add a course using AddCourse.js component on submitting the form, then you want to display the course ID, Title and Description. In order to do this, you need the following:
1 - localStorage,
2 - Context API or Redux,
3 - Create a new state on your Context API or redux to store the values and pass it down to children components, in your example courses.js
If I understand correctly you want to switch between viewing a course and editing/updating a course?
One way to achieve this is:
const Course = ({ course }) => {
const user = useSelector((state) => state.auth.user.uid);
const dispatch = useDispatch();
const removeCourse = (id) => {
console.log(id);
const dbtasksWrapper = database.ref().child(user).child('courses');
dbtasksWrapper
.child(id)
.remove()
.then(() => {
dispatch({ type: 'DELETE_COURSE', id });
dispatch(fetchCourse(user));
});
};
// state to switch between updating the course and viewing the course
const [isUpdating, setIsUpdating] = useState(false);
return (
<div>
{isUpdating ? (
{/* pass the course down and a callback to close update component */}
<AddCourse course={course} finishUpdate={() => setIsUpdating(false)} />
) : (
<Card>
<CardBody className="text-center ">
<CardText className="text-center">
<h2>CourseID: {course.courseId}</h2>
</CardText>
<CardTitle className="font-weight-bold text-center">
<h1>{course.courseTitle}</h1>
</CardTitle>
<CardText className="text-center">{course.courseDesc}.</CardText>
<Container className="text-center">
{/* Set isUpdating to true */}
<Button color="warning" onClick={() => setIsUpdating(true)}>
Update
</Button>
<Button color="danger ml-4" onClick={() => removeCourse(course.id)}>
Delete
</Button>
</Container>
</CardBody>
</Card>
)}
</div>
);
};
This will change depending on your setup, if this isn't what you wanted please provide some more details about how you would like this to function.

Why doesn't this React component re-render when its prop changes?

I've created a cut-down version of a re-render issue which I'm having with an application I am working on.
In reality DisplayElement1 and DisplayElement2 are two complex components.
DisplayElement2 here is iterating through a simple array of numbers (supplied via its prop numbers) and displaying them.
Problem : When the array behind the numbers prop gets updated in the main component App (in this case by clicking on the Add Number to Array button I would expect DisplayElement2 to re-render with the updated array but it doesn't, why not ??
If I click Show Display 1 and then click back on Show Display 2 the updated array renders.
App.js
import React, { useState, useMemo } from "react";
import "./styles.css";
import DisplayComponent1 from "./DisplayComponent1";
import DisplayComponent2 from "./DisplayComponent2";
import { Button } from "#material-ui/core";
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
////////////////////////////////////////////////
const component1 = useMemo(() => {
return <DisplayComponent1 />;
}, []);
const component2 = useMemo(() => {
return (
<DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>
);
}, [numbersToDisplay]);
////////////////////////////////////////////////
const [currentDisplayComponent, setCurrentDisplayComponent] = useState(
component2
);
return (
<div className="App">
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent(component1)}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent(component2)}
>
Show Display 2
</Button>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{currentDisplayComponent}
</div>
);
}
DisplayElement1.js and DisplayElement2.js
import React from "react";
import {Paper} from "#material-ui/core";
export default function DisplayComponent1(props) {
return (
<Paper>
<p>This is DisplayComponent1</p>
</Paper>
);
}
import React from "react";
import { Paper } from "#material-ui/core";
export default function DisplayComponent2(props) {
return (
<Paper>
<p>This is DisplayComponent2</p>
{props.numbers.map((currNumber, currIndex) => {
return <div key={currIndex}>{currNumber}</div>;
})}
</Paper>
);
}
The reason your component doens't re-render with updated props is because you have a previous instance of your component stored in the currentDisplayComponent state which is what you use to render
A hacky workaround with your current code would be to make use of useEffect and update the component instance that is active
However the best solution in this scenarios is to take out the component instances outside of the state and render these based on a selected component string state.
To prevent unnecessary updates you can make use of React.memo
export default React.memo(function DisplayComponent2(props) {
return (
<Paper>
<p>This is DisplayComponent2</p>
{props.numbers.map((currNumber, index) => {
return <div key={index}>{currNumber}</div>;
})}
</Paper>
);
});
App.js
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
const [currentDisplayComponent, setCurrentDisplayComponent] = useState(
"component1"
);
const getCurrentComponent = currentDisplayComponent => {
switch (currentDisplayComponent) {
case "component1":
return <DisplayComponent1 />;
case "component2":
return (
<DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>
);
default:
return null;
}
};
return (
<div className="App">
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent("component1")}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent("component2")}
>
Show Display 2
</Button>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{getCurrentComponent(currentDisplayComponent)}
</div>
);
}
Working demo
Consider something like this for your App.js, where the display states are enumerated and we've removed the useMemo
import React, { useState } from "react";
import "./styles.css";
import DisplayComponent1 from "./DisplayComponent1";
import DisplayComponent2 from "./DisplayComponent2";
import { Button } from "#material-ui/core";
const DisplayStatEnum = {COMPONENT1: 0, COMPONENT2: 1};
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
////////////////////////////////////////////////
const component1 = <DisplayComponent1 />;
const component2 = <DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>;
////////////////////////////////////////////////
const [currentDisplayComponent, setCurrentDisplayComponent]
= useState(DisplayStatEnum.COMPONENT2);
const componentSelected =
currentDisplayComponent === DisplayStatEnum.COMPONENT1
? component1
: component2;
return (
<div className="App">
<div>
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT1)}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT2)}
>
Show Display 2
</Button>
</div>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{componentSelected}
</div>
);
}

Jest Test of Material-UI Component to Simulate Button click event to fire a Redux Action function

Not able to test button.simulate("click") on a Material-UI based Component having Button which fires 'loadAllData()' function on its onClick prop.
The below is my hooks based component
The full code for this component is here
const GithubMostPopularList = () => {
const globalStore = useSelector(state => state.globalStore)
const dispatch = useDispatch()
const loadAllData = () => {
const city = globalStore.city_to_search
setcurrentCityShown(city)
dispatch(loadMostPopularUsers(city, page, rowsPerPage))
}
return (
<div className={classes.container}>
<div className={classes.tableAndFabContainer}>
{globalStore.loading ? (
<div className={classes.spinner}>
<LoadingSpinner />
</div>
) : (
<div className={classes.table}>
<div className={classes.inputandButtonContainer}>
<Button
onClick={loadAllData}
variant="contained"
size="large"
color="primary"
disabled={globalStore.city_to_search === ""}
>
<Typography
variant="h3"
className={classes.modalButtonLabelEnabled}
>
Load City Data
</Typography>
</Button>
</div>
<div style={{ marginTop: "20px" }}>
<EachUserListItem
currentCityShown={currentCityShown}
></EachUserListItem>
</div>
</div>
)}
</div>
</div>
)
}
export default GithubMostPopularList
And below is my test, which fails giving me `TypeError: Cannot read property 'loadAllData' of null'
it("should trigger onClick on on Button press", () => {
const wrapperComp = mount(
<Provider store={store}>
<MuiThemeProvider theme={globalTheme}>
<GithubMostPopularList />
</MuiThemeProvider>
</Provider>,
)
const spy1 = jest.spyOn(wrapperComp.instance(), "loadAllData")
const button = wrapperComp.find(Button).last()
button.simulate("click")
wrapperComp.update()
expect(spy1).toHaveBeenCalledTimes(1)
})
Will highly appreciate any guidance or help.
I assume you had to use mount to avoid the error of shallowing a material component without a provider.
but here is what I usually do. I unwrap the component then it is ok to shallow it.
import unwrap from '#material-ui/core/test-utils/unwrap';
const UnwrappedComponent: any = unwrap((GithubMostPopularList as unknown as React.ReactElement<any>));
it('should trigger onClick on on Button press', () => {
const wrapperComp = shallow(<UnwrappedComponent />);
jest.spyOn(wrapperComp.instance(), 'loadAllData');
const button = wrapperComp.find(Button);
button.simulate('click');
wrapperComp.update();
expect(wrapperComp.instance().loadAllData).toHaveBeenCalledTimes(1);
});

Updating state and backend

I'm wondering on the best way to do a HTTP PUT with my react application. I have a Post component that fetches data from https://jsonplaceholder.typicode.com/posts/1 and displays the data.
I have another component EditPost that when clicked on button "Edit" displays a dialog where the user can edit the post. The current data is sent to EditPost with a prop.
Questions
Is it best to hold the state in the Post component?
If so, should the update of state and HTTP PUT call be placed in the Post component
How can I update eg. title and not the other attributes of post?
Post component
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import Hello from './Hello';
import axios from "axios";
function Post() {
const [post, setPost] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const result = await axios(
"https://jsonplaceholder.typicode.com/posts/1"
);
setPost(result.data);
} catch (error) {console.log(error)}
};
fetchData();
}, []);
return(
<div>
<h1>{post? post.id: ""}</h1>
<h1>{post? post.title: ""}</h1>
<h1>{post? post.body: ""}</h1>
<EditPost value={post}/>
</div>)
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Post/>, rootElement);
}
Edit Post component:
import React from "react";
import Button from "#material-ui/core/Button";
import TextField from "#material-ui/core/TextField";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
export default function EditPost(props) {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
function handleSubmit() {
//Do something
}
return (
<form onSubmit={handleSubmit}>
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Update Post
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Update Post</DialogTitle>
<DialogContent>
<DialogContentText>Update Post</DialogContentText>
<TextField
autoFocus
margin="dense"
id="title"
label="title"
value={props.value.title}
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="body"
label="body"
value={props.value.body}
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="id"
label="id"
value={props.value.id}
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button color="primary" type="submit">
OK
</Button>
</DialogActions>
</Dialog>
</div>
</form>
);
}
Yes it is a good practice to handle the state of your form in the component so to do it that way you will need minor modifications on your code.
You are missing a function to handle the values that you want to modify, so you can update it with your service and have the same state on the backend and on the ui.
First you need a the variables to store your title (and the other props) state, lets make an example with the title.
const [title, setTitle] = useState('');
You also can set the title as the prop of your data that the parent component is requesting:
const [title, setTitle] = useState(props.value.title);
Then you have to create a function that handles the title state.
const handleTitle = ( e ) => {
setTitle(e.target.value);
}
You have to add this function to you TextField component.
<TextField
autoFocus
margin="dense"
id="title"
label="title"
value={title}
onChange={handleTitle}
fullWidth
/>
When you have all yoiur methods that handle the props of your object, in this case is : title, body and id, you will need a method to submit all this data to your service.
const handleSubmit = () => {
const newData = {title: title, id: id, body: body };
//So here you will submit your data , and when the data is successfully submited you will have to update you Parent state to have the same post data in both components, so you will have to pass your 'setPost' method to EditPost Component to be able to do this:
props.setPost(newData)
}
So to pass the method to update the current post you have to do something like this in your EditPost declaration:
<EditPost setPost={setPost} value={post}/>
I think It's best if you had parent component which holds the state of post and http callbacks and 2 child component for view and edit.
const App = props => {
// Post state here
// http callbacks, put get etc.
return(
<PostView {...viewProps}/>
<PostEdit {...editProps}/>
)
}
As for your last question you can use 3rd party form manager such as Formik or react-hooks-form which is helpful mostly because of form validation imo. or you can do it yourself.
If you do it yourself you need to save the inputs state by supplying onChange callback. here's an example:
export default function EditPost(props) {
const [open, setOpen] = React.useStat(false);
const [formState, setFormState] = React.useState({...props.initialValues})
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
function handleSubmit(e) {
e.preventDefault();
// lift formState to <App/>
props.onSubmit(formState.title);
}
const handleChange = e => {
const {name, value} = e.target;
// can do some validation here before saving the state
setFormState(prevState => ({...prevState, [name]: value}))
}
return (
<form onSubmit={handleSubmit}>
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Update Post
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Update Post</DialogTitle>
<DialogContent>
<DialogContentText>Update Post</DialogContentText>
<TextField
autoFocus
margin="dense"
id="title"
label="title"
value={formState.title}
name="title"
onChange={handleChange}
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="body"
label="body"
name="body"
value={formState.body}
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="id"
label="id"
name="id"
value={formState.id}
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button color="primary" type="submit">
OK
</Button>
</DialogActions>
</Dialog>
</div>
</form>
);
}

Categories

Resources