test react form submit with conditions which button clicked - javascript

React beginner on testing, i'm testing form submits, i have tested already few form submits successfully, but this one has 'Accept' button AND 'Delete' button and both uses same 'handleSubmit' function so thats why i have conditions inside that function, depending on which clicked. I need some advice on how to test form submit when
”Accept” button is clicked ?
English is not my mother language so could be mistakes. If any question just ask me.
My test will pass only if i delete one of those buttons but i need both.
test:
import React from "react";
import {
render,
screen,
RenderResult,
cleanup,
fireEvent,
getByRole,
getByDisplayValue,
} from "#testing-library/react";
const onFormSubmit = jest.fn();
const currentCamera = "0-0-0-2";
describe("Testing component", () => {
const AddCamera = () =>
render(
<Provider store={store}>
<MemoryRouter>
<CameraForm onSubmit={onFormSubmit} key={"cameraform-" + currentCamera} />
</MemoryRouter>
</Provider>
);
test("Testing Add Camera", () => {
AddCamera();
const AddName = screen.getByTestId(/^AddName/i);
expect(AddName).toBeInTheDocument();
fireEvent.change(AddName, { target: { value: "Camera 2" } });
expect(AddName).toHaveValue("Camera 2");
fireEvent.submit(screen.getByTestId("renderAddForm"));
expect(onFormSubmit).toHaveBeenCalled();
});
});
code:
import {
...
} from "#material-ui/core/";
const handleSubmit = (event) => {
event.preventDefault();
if (state.button === 1) {
if (!Camera) {
return;
}
const { name} = state;
refresh();
dispatch(
addCamera(site.identifier, Camera.identifier, {
name
})
);
externalOnSubmit();
}
if (state.button === 2) {
event.preventDefault();
if (!Camera) {
return;
}
refresh();
dispatch(
deleteCamera(site.identifier, Camera.identifier)
);
externalOnSubmit();
}
};
const renderAdd = () => {
const { helperText, error, name } = state;
return (
<React.Fragment>
<Box sx={boxStyle} data-testid="CameraForm">
<form
data-testid="renderAddForm"
onSubmit={handleSubmit}>
<div className="handle">
<Box>
<Button
onClick={nulll}
aria-label="close-settings-popup">
<Close />
</Button>
</Box>
</div>
<div>
<FormGroup>
<Box>
<FormControl>
<TextField
helperText={helperText.name}
error={error.name}
inputProps={{
"data-testid": "AddName",
}}
InputProps={{
className: classes.underline,
}}
InputLabelProps={{
className: classes.inputLabelColor,
}}
required={true}
type="text"
id="name"
value={name}
onChange={handleChange}
label='Name'
></TextField>
</FormControl>
</Box>
</FormGroup>
</div>
{!state.readOnly ? (
<div>
<Button
onClick={() => (state.button = 2)}
type="submit"
>
<Trans i18nKey="form.delete">Delete</Trans>
</Button>
<Button
data-testid="submitButton"
onClick={() => (state.button = 1)}
type="submit"
variant="contained"
color="primary"
disabled={
!currentSite ||
Object.values(state.error).some((v) => {
return v === true;
})
}
className={classes.button_basic}
startIcon={<Done />}
>
Accept
</Button>
</div>
) : (
""
)}
</form>
</Box>
</React.Fragment>
);
};

Related

React hook form loosing data on inputs when calling watch

I have a form that uses accordion component.
When I print values using watch() then collapse accordion. the values get deleted from inputs when I open it again.
This behaviour is not happening when I don't use watch()
I would like to know why this is happening ? watch() should only listen to data as I know.
CodeSandbox
CreateTest.ts
import { QuestionCreatingForm } from "./QuestionForm";
import {
AccordionHeader,
AccordionItem,
AccordionPanel,
Accordion
} from "#fluentui/react-components";
import { Button, Form } from "#fluentui/react-northstar";
import { useFieldArray, useForm } from "react-hook-form";
export function CreateTest() {
const methods = useForm();
const { control, register, handleSubmit, watch } = methods;
const { fields, append } = useFieldArray({
control,
name: "questions"
});
const addQuestion = (event: any) => {
event.preventDefault();
append({ name: "" });
};
const onSubmit = (data: any) => {
alert(JSON.stringify(data));
};
return (
<div className="w-8/12 m-auto">
{JSON.stringify(watch())}
<Form onSubmit={handleSubmit(onSubmit)}>
{fields.map((field, index) => (
<Accordion key={field.id} collapsible>
<AccordionItem value="1">
<AccordionHeader>Accordion Header </AccordionHeader>
<AccordionPanel>
<QuestionCreatingForm
fieldId={field.id}
index={index}
{...{ control, register, watch }}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
))}
<Button
className="my-10"
content="Add question"
primary
fluid
onClick={addQuestion}
/>
<Button
className="my-10"
fluid
content="submit"
primary
type="submit"
/>
</Form>
{/* </FormProvider> */}
</div>
);
}
QuestionForm.ts
import {
Button,
Divider,
FormCheckbox,
FormInput,
TrashCanIcon
} from "#fluentui/react-northstar";
import { SyntheticEvent } from "react";
import {
Control,
FieldValues,
useFieldArray,
UseFormRegister,
UseFormWatch
} from "react-hook-form";
export function QuestionCreatingForm({
index,
fieldId,
control,
register,
watch
}: {
index: number;
fieldId: string;
control: Control<FieldValues, any>;
register: UseFormRegister<FieldValues>;
watch: UseFormWatch<FieldValues>;
}) {
const { fields, append, remove } = useFieldArray({
control,
name: `questions.${index}.responses`
});
const addResponse = (event: SyntheticEvent<HTMLElement, Event>) => {
event.preventDefault();
append({ name: "" });
};
const deleteResponse = (index: number) => {
remove(index);
};
return (
<>
<FormInput
label="Question"
required
fluid
key={index}
{...register(`questions.${index}.name` as const)}
/>
<div className="w-10/12 m-auto">
{fields.map((field, i) => (
<div className="flex w-full">
<FormCheckbox />
<div className="w-full" key={field.id}>
<FormInput
{...register(`questions.${index}.responses.${i}.name` as const)}
defaultValue=""
label={`reponses ${i + 1}`}
required
fluid
/>
</div>
<Button
text
styles={{ color: "red", placeSelf: "end" }}
icon={<TrashCanIcon />}
onClick={(e) => deleteResponse(i)}
iconOnly
/>
</div>
))}
<Button
content="Ajouter une réponse"
tinted
fluid
onClick={addResponse}
/>
</div>
<Divider />
</>
);
}

How to properly control focus and blur events on a React-Bootstrap InputGroup?

I have a single input element from react-bootstrap that will allow the user to change the field value and 2 buttons will appear, one to accept the changes and the other will cancel the changes leaving the original value in.
I manage to control the focus and blur events by delegating the listeners to the wrapping component, my thinking is that since the focus is still within the wrapping component, I won't lose its focus, but pressing the inner buttons seems to blur the focus, therefore the Accept and Cancel buttons don't fire any events...
Here is my code example:
import { useState, useEffect, useRef } from "react";
import { InputGroup, Button, FormControl } from "react-bootstrap";
import "./styles.css";
const InputField = ({ title }) => {
const formRef = useRef(null);
const [value, setValue] = useState(title);
const [toggleButtons, setToggleButtons] = useState(false);
const onChange = (e) => {
setValue(e.target.value);
};
const onFocus = () => {
setToggleButtons(true);
};
const onBlur = () => {
setToggleButtons(false);
};
const acceptChange = () => {
console.log("Accept");
setToggleButtons(false);
};
const cancelChange = () => {
console.log("Cancel");
setToggleButtons(false);
};
useEffect(() => {
const form = formRef.current;
form.addEventListener("focus", onFocus);
form.addEventListener("blur", onBlur);
return () => {
form.removeEventListener("focus", onFocus);
form.removeEventListener("blur", onBlur);
};
}, []);
return (
<div className="App">
<InputGroup className="m-3" style={{ width: "400px" }}>
<FormControl
ref={formRef}
value={value}
onChange={onChange}
// onFocus={onFocus}
// onBlur={onBlur}
/>
{toggleButtons ? (
<InputGroup.Append>
<Button variant="outline-secondary" onClick={() => acceptChange()}>
Accept
</Button>
<Button variant="outline-secondary" onClick={() => cancelChange()}>
Cancel
</Button>
</InputGroup.Append>
) : null}
</InputGroup>
</div>
);
};
export default function App() {
return (
<>
<InputField title={"Input 1"} />
<InputField title={"Input 2"} />
<InputField title={"Input 3"} />
<InputField title={"Input 4"} />
</>
);
}
A couple of changes are needed to make this work:
The toggle buttons need to always be in the DOM, so hide them rather than only rendering if the focus is there.
To avoid hiding the buttons when the blur occurs from the input to one of the buttons you can check if the newly focused element is a sibling of the input by using the event's relatedTarget and the currentTarget.parentNode.
For example:
import { useState } from "react";
import { InputGroup, Button, FormControl } from "react-bootstrap";
import "./styles.css";
const InputField = ({ title }) => {
const [value, setValue] = useState(title);
const [toggleButtons, setToggleButtons] = useState(false);
const onChange = (e) => {
setValue(e.target.value);
};
const onFocus = () => {
setToggleButtons(true);
};
const onBlur = (e) => {
if (!e.currentTarget.parentNode.contains(e.relatedTarget)) {
setToggleButtons(false);
}
};
const acceptChange = () => {
console.log("Accept");
setToggleButtons(false);
};
const cancelChange = () => {
console.log("Cancel");
setToggleButtons(false);
};
return (
<div className="App">
<InputGroup className="m-3" style={{ width: "400px" }}>
<FormControl
value={value}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
/>
<InputGroup.Append className={toggleButtons ? "d-flex" : "d-none"}>
<Button
onBlur={onBlur}
variant="outline-secondary"
onClick={() => acceptChange()}
>
Accept
</Button>
<Button
onBlur={onBlur}
variant="outline-secondary"
onClick={() => cancelChange()}
>
Cancel
</Button>
</InputGroup.Append>
</InputGroup>
</div>
);
};
export default function App() {
return (
<>
<InputField title={"Input 1"} />
<InputField title={"Input 2"} />
<InputField title={"Input 3"} />
<InputField title={"Input 4"} />
</>
);
}
https://codesandbox.io/s/input-group-focus-slwoh

How can I add onChange to my onClick function?

Been struggling to try and solve this one,
I have a <form> that is wrapped around a Controller using a render. The render is a list of <Chip>'s. I want the list of chips to act as a field, each user toggled chip would act as the data inputted to the form, based on the label value of a chip. The expected data can be either one string or an array of strings based on how many <Chips> are toggled.
I've tried to replicate examples that use <Checkbox>, but I wasn't able to re-create the component.
I have a state of total chips toggled, which re-produces the data I would like to submit via my button. Is there a way to pass this state to my form data?
I'm currently only able to submit empty data through my form because my chip values and form data are not linked up correctly.
To solve this I need to add onChange to my onClick parameter for <Chip>, I've tried doing this:
onClick={(value, e) => { handleToggle(value); onChange(value) }}
But that does not work?
Here is my Form
<form noValidate onSubmit = { handleSubmit(onSubmit) }>
<Controller
render={({ onChange ,...props }) => (
<Paper component="ul" className={classes.root}>
{stocklist.map((value, index) =>
{
return (
<li key={index}>
<Chip
name="stock_list"
variant="outlined"
label={value}
key={index}
color={checked.includes(value) ? 'secondary' : 'primary'}
onClick={handleToggle(value)}
className={classes.chip}
ref={register}
/>
</li>
);
})}
</Paper>
)}
name="stock_list"
control={control}
defaultValue={[]}
onChange={([, data]) => data}
/>
{checked && checked.length > 0 &&
<Fab
color="primary"
aria-label="delete"
type="submit"
>
<DeleteIcon />
</Fab>
}
</form>
Here is how I toggle the chips, and create a state checked which holds the values for every toggled chip
const { register, control, handleSubmit } = useForm();
const [checked, setChecked] = React.useState([]);
const handleToggle = (value) => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
};
Here is my onSubmit function
const onSubmit = (data, e) =>
{
console.log(data);
axiosInstance
.patch('url', {
stock_list: data.stock_list,
})
.then((res) =>
{
console.log(res);
console.log(res.data);
});
};
Check it out https://codesandbox.io/s/cocky-roentgen-j0pcg Please toggle one of the chips, and then press the button that appears. If you then check the console, you will notice an empty form array being submitted.
I guess this will work for you
import React, { useState } from "react";
import { Chip, Paper, Fab, Grid } from "#material-ui/core/";
import { makeStyles } from "#material-ui/core/styles";
import { Controller, useForm } from "react-hook-form";
import DeleteIcon from "#material-ui/icons/Delete";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
listStyle: "none",
padding: theme.spacing(0.5),
margin: 0,
"#media (max-width: 600px)": {
overflowY: "auto",
height: 200
}
},
chip: {
margin: theme.spacing(0.5)
}
}));
export default function app() {
const { register, control, handleSubmit } = useForm();
const classes = useStyles();
const [checked, setChecked] = React.useState([]);
const stocklist = ["AAPL", "AMD", "TSLA"];
const onSubmit = (data, e) => {
console.log("data.stock_list");
console.log(data.stock_list);
console.log("data.stock_list");
};
const handleToggle = (value) => {// <== I changed this part
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
return newChecked;// <== I changed this part
};
return (
<>
{(!stocklist || stocklist.length === 0) && (
<p style={{ textAlign: "center" }}>Your Bucket is empty...</p>
)}
{stocklist && stocklist.length > 0 && (
<Grid>
<form noValidate onSubmit={handleSubmit(onSubmit)}>
<Controller
name="stock_list"// <== I changed this part
render={({ onChange, ...props }) => (
<Paper component="ul" className={classes.root}>
{stocklist.map((value, index) => {
return (
<li key={index}>
<Chip
// name="stock_list"// <== I changed this part
variant="outlined"
label={value}
key={index}
color={
checked.includes(value) ? "secondary" : "primary"
}
onClick={(e) => {
onChange(handleToggle(value));// <== I changed this part
}}
className={classes.chip}
ref={register}
/>
</li>
);
})}
</Paper>
)}
control={control}
defaultValue={{}}
onChange={([, data]) => data}
/>
{checked && checked.length > 0 && (
<Fab color="primary" aria-label="delete" type="submit">
<DeleteIcon />
</Fab>
)}
</form>
</Grid>
)}
</>
);
}

Using React Router to Redirect to next page after successful login

I have created a basic MERN log in page and I am a bit confused on how to redirect the user after a successful log in. I have created a Log in context and when a user successfully logs in I set logged in state to true. I am unsure how I can then redirect to /items route. Any help would be appreciated. Here is my App code:
function App() {
return (
<LoggedInProvider>
<ThemeProvider>
<Switch>
<Route
exact
path="/"
render={() => <SignIn />}
/>
<Route
exact
path="/items"
render={() => <Index />}
/>
</Switch>
</ThemeProvider>
</LoggedInProvider>
);
}
export default App;
Here is my SignIn component:
function Form(props) {
const { isDarkMode } = useContext(ThemeContext);
const { loggedIn, changeLogIn } = useContext(LoggedInContext);
const [isSignUp, setSignUp] = useState(false);
const { classes } = props;
const [usernameValue, setUsernameValue] = useState('');
const [passwordValue, setPasswordValue] = useState('');
const handleUsernameChange = (e) => {
setUsernameValue(e.target.value);
};
const handlePasswordChange = (e) => {
setPasswordValue(e.target.value);
};
// const [value, setValue] = useState(initialVal);
// const handleChange = (e) => {
// setValue(e.target.value);
// };
const handleClick = () => {
setSignUp(!isSignUp);
};
const reset = () => {
setUsernameValue('');
setPasswordValue('');
};
const authSubmitHandler = async (event) => {
event.preventDefault();
if (!isSignUp) {
try {
const response = await fetch('http://localhost:8181/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: usernameValue,
password: passwordValue,
}),
});
const responseData = await response.json();
if (responseData.code === 200) {
console.log('Success Response');
changeLogIn(true);
reset();
}
console.log('This is a response');
console.log(responseData);
} catch (err) {
console.log(err);
}
} else {
try {
const response2 = await fetch('http://localhost:8181/auth', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: usernameValue,
password: passwordValue,
}),
});
const responseData2 = await response2.json();
console.log(responseData2);
} catch (err) {
console.log(err);
}
}
};
return (
<main className={classes.main}>
{!isSignUp ? (
<Paper
className={classes.paper}
style={{ background: isDarkMode ? '#2E3B55' : 'white' }}
>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography variant="h5">Sign In</Typography>
<form
className={classes.form}
onSubmit={authSubmitHandler}
>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="username">Username</InputLabel>
<Input
id="username1"
name="username1"
value={usernameValue}
onChange={handleUsernameChange}
autoFocus
/>
</FormControl>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="password">Password</InputLabel>
<Input
id="password"
name="password"
type="password"
value={passwordValue}
onChange={handlePasswordChange}
autoFocus
/>
</FormControl>
<Button
variant="contained"
type="submit"
fullWidth
color="primary"
className={classes.submit}
>
Sign In
</Button>
</form>
<Button
variant="contained"
type="submit"
fullWidth
color="secondary"
className={classes.submit}
onClick={handleClick}
>
Switch to Sign up
</Button>
</Paper>
) : (
<Paper
className={classes.paper}
style={{ background: isDarkMode ? '#2E3B55' : 'white' }}
>
<Avatar className={classes.avatar}>
<LockOutlinedIcon color="primary" />
</Avatar>
<Typography variant="h5">Sign Up</Typography>
<form
className={classes.form}
onSubmit={authSubmitHandler}
>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="username">Username</InputLabel>
<Input
id="username2"
name="username"
value={usernameValue}
onChange={handleUsernameChange}
autoFocus
/>
</FormControl>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="password">Password</InputLabel>
<Input
id="password"
name="password"
type="password"
value={passwordValue}
onChange={handlePasswordChange}
autoFocus
/>
</FormControl>
<Button
variant="contained"
type="submit"
fullWidth
color="primary"
className={classes.submit}
>
Sign Up
</Button>
</form>
<Button
variant="contained"
type="submit"
fullWidth
color="secondary"
className={classes.submit}
onClick={handleClick}
>
Switch to Sign In
</Button>
</Paper>
)}
</main>
);
}
// class Form extends Component {
// static contextType = LanguageContext;
// render() {
// return (
// );
// }
// }
export default withStyles(styles)(Form);
And here is my log in context:
import React, { createContext, useState } from 'react';
export const LoggedInContext = createContext();
export function LoggedInProvider(props) {
const [loggedIn, setLoggedIn] = useState(false);
const changeLogIn = (val) => {
setLoggedIn(val);
};
return (
<LoggedInContext.Provider value={{ loggedIn, changeLogIn }}>
{props.children}
</LoggedInContext.Provider>
);
}
In your LoggedInProvider component you can do something like this:
import { useHistory } from "react-router-dom";
import React, { createContext, useState } from "react";
export const LoggedInContext = createContext();
export function LoggedInProvider(props) {
const history = useHistory();
const [loggedIn, setLoggedIn] = useState(false);
const changeLogIn = (val) => {
setLoggedIn(val);
if(val) NavigateAway('/items');
};
const NavigateAway = path => {
history.push(path);
}
return (
<LoggedInContext.Provider value={{ loggedIn, changeLogIn }}>
{props.children}
</LoggedInContext.Provider>
);
}
Hope this work's for you.
Just use props.history.push(). Every route's component will have access to the history object attached to it. As a reference:
const Login = ({ history }) => {
// username, password state fields here
function login(e) {
e.preventDefault();
login({ username, password })
.then(() => {
// set your authentication credentials to some persistent store
history.push('/items');
});
}
return (
// login form markup in here
);
};
well, the easiest way to do is to use the history object available in your props.
Try to see if it exist, you can do the following:
this.props.history.push('/item'): this should redirect you to the page.
Link from react-router-dom: it contains a property called redirect

Using modal to add a new data to mui-datatable

I need to create a new data using a modal box and this is how I implemented it but apparently the new data is not being added in the datatable. Is their a way to do this?
Here is my code:
let id = 0;
function createData(name, provider){
id += 1;
return [id, name, provider];
}
const data = [
createData("Dummy1", "oracle"),
createData("Dummy2", "mssql"),
createData("Dummy3", "oracle"),
];
function ModalBox(props){
const [open, setOpen] = React.useState(false);
const [state, setState] = React.useState({
dname: '',
dsource: '',
data
})
const handleChange = name => e =>{
setState({
...state,
[name]: e.target.value,
})
}
const handleClickOpen = () => {
setOpen(true);
}
const handleClose = () => {
setOpen(false);
}
const addDataSource = () =>{
data.push(createData(state.dname, state.dsource));
setOpen(false);
}
return(
<div>
<Button variant="contained" color="primary" onClick={handleClickOpen}>
Create New
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send
updates occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
type="text"
value={state.dname || ''}
onChange={handleChange('dname')}
fullWidth
/>
<Select
native
fullWidth
value={state.dsource || ''}
onChange={handleChange('dsource')}
>
<option value="" />
<option value={'mssql'}>mssql</option>
<option value={'oracle'}>oracle</option>
</Select>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={addDataSource} color="primary">
Add
</Button>
</DialogActions>
</Dialog>
</div>
);
}
function TestSource(){
const columns = ["Id", "Name", "Provider"];
const options = {
filterType: 'checkbox',
};
return(
<div className="f-height fx-column-cont">
<MainToolbar/>
<Container>
<ModalBox/>
<MUIDataTable
title={"Test Source"}
data={data}
columns={columns}
options={options}
/>
</Container>
</div>
);
}
export default TestSource;
I think the problem is that I have a global array and I try to push new data inside a function. Is there a way to work around this in? Appreciate any advise you could provide on this.
You could lift the state up to the parent component:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import {
Button,
Select,
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
TextField,
DialogActions
} from "#material-ui/core";
import "./styles.css";
function ModalBox(props) {
const [open, setOpen] = useState(false);
const [state, setState] = useState({
dname: "",
dsource: ""
});
const handleChange = name => e => {
setState({
...state,
[name]: e.target.value
});
};
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="contained" color="primary" onClick={handleClickOpen}>
Create New
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here.
We will send updates occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
type="text"
value={state.dname || ""}
onChange={handleChange("dname")}
fullWidth
/>
<Select
native
fullWidth
value={state.dsource || ""}
onChange={handleChange("dsource")}
>
<option value="" />
<option value={"mssql"}>mssql</option>
<option value={"oracle"}>oracle</option>
</Select>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button
onClick={() => {
props.addDataSource(state.dname, state.dsource);
setOpen(false);
}}
color="primary"
>
Add
</Button>
</DialogActions>
</Dialog>
</div>
);
}
function App() {
const columns = ["Id", "Name", "Provider"];
const [data, setData] = useState([]);
let id = 0;
function createData(name, provider) {
id += 1;
return [id, name, provider];
}
useEffect(() => {
const data = [
createData("Dummy1", "oracle"),
createData("Dummy2", "mssql"),
createData("Dummy3", "oracle")
];
setData(data);
}, []);
const options = {
filterType: "checkbox"
};
const addDataSource = (dname, dsource) => {
const updated = [...data];
updated.push(createData(dname, dsource));
setData(updated);
};
return (
<div className="f-height fx-column-cont">
<div>
<ModalBox
addDataSource={(dname, dsource) => addDataSource(dname, dsource)}
/>
<MUIDataTable
title={"Test Source"}
data={data}
columns={columns}
options={options}
/>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I would also suggest to crate different files for the components and do some refactoring and cleanup :-) Hope that helps.

Categories

Resources