my backend does queryset filtering against the url parameters. On my frontend, depending whether a checkbox is ticked or not i wanna add a string (for example "?category=cardgame") to the axios url. Im not too sure how to do it
i was thinking of something like
button1ticked && (url += string-associated-with-button1)
but idk how to actually write it in react. I know its a beginner question but thanks for helping!
Use The WHATWG URL API
You can use the urlSearchParams.set(name, value)
import { useEffect, useState } from "react";
import "./styles.css";
import axios from "axios";
function CheckBox({ name, onChange, category, initialState = false }) {
const [isChecked, setIsChecked] = useState(initialState);
function handleOnChange(event) {
const isChecked = !!event.target.checked;
setIsChecked(isChecked);
if (onChange) onChange(isChecked, { category: category });
}
return (
<div className="App">
<input
onChange={handleOnChange}
name={name}
checked={isChecked}
type="checkbox"
/>
</div>
);
}
export default function App() {
const [url, setUrl] = useState("https://randomuser.me/api/?results=5");
function onChange(checked, filter) {
getList(filter, checked);
}
function buildUrl(filter, addFilter) {
let newUrl = new URL(url);
if (filter) {
Object.keys(filter).forEach((key) => {
if (addFilter) {
newUrl.searchParams.set(key, filter[key]); // append param
} else {
newUrl.searchParams.delete(key); // remove param
}
});
}
return newUrl.toString();
}
function getList(filter, addFilter) {
const newURL = buildUrl(filter, addFilter);
setUrl(newURL);
axios
.get(newURL)
.then(response => {
console.log(response);
})
.then(users => {
this.setState({
users,
isLoading: false
});
})
.catch(error => this.setState({ error, isLoading: false }));
}
useEffect(() => {
getList(null, false);
}, []);
return (
<div className="App">
<CheckBox
onChange={onChange}
category="cardgame"
name="check-box-name"
initialState={true}
/>{" "}
Checkbox 1
<CheckBox
onChange={onChange}
category="boardgame"
name="check-box-name"
initialState={true}
/>{" "}
Checkbox 2
<CheckBox
onChange={onChange}
category="videogame"
name="check-box-name"
initialState={true}
/>{" "}
Checkbox 3
</div>
);
}
Related
My edit function is overriding the local storage when I try to save and even messing with my delete function. not sure where is the issue. I tried finding the solution in similar posts but could not figure it out. GitHub repo for full code: https://github.com/ottowoolf/NotesApp.
import React, { useState, useEffect } from "react";
import { Form, Container, Button } from "react-bootstrap";
import { useParams } from "react-router-dom";
export const Edit = ({ notes, setNotes }) => {
const [form, setForm] = useState({
title: "",
text: "",
id: "",
});
const { id } = useParams();
useEffect(() => {
let index = notes.find((n) => n.id === id);
let selectedNote = notes[index];
console.log(notes[index]);
console.log(id);
console.log(selectedNote);
setForm(selectedNote);
}, [id, notes]);
const handleChange = (e) => {
const { value, name } = e.target;
setForm({ ...form, [name]: value, id });
console.log(form);
};
const saveNote = () => {
if (form.title.trim() !== "" || form.text.trim() !== "") {
setNotes((note) => {
// return array - with the object of /id/ modified
let index = note.find((n) => n.id === id);
let newNotes = [...note];
newNotes[index] = form;
console.log(newNotes[index]);
return newNotes[index];
});
}
};
return (
<React.Fragment>
<Container>
<Form className='mt-3 w-50'>
<Form.Group controlId='formBasicEmail'>
<Form.Control
onChange={handleChange}
value={form.title}
name='title'
type='text'
/>
</Form.Group>
<Form.Group controlId='formBasicPassword'>
<Form.Control
onChange={handleChange}
value={form.text}
name='text'
as='textarea'
cols='30'
rows='10'
/>
</Form.Group>
</Form>
<Button onClick={saveNote} className='btn btn-success'>
Save
</Button>
</Container>
</React.Fragment>
);
};
Forked your GitHub repo and edited it using codesandbox
Here is the link
https://codesandbox.io/s/aged-dawn-bnv6v?file=/src/pages/Edit.js
Tell me if anything is missing.
Also, I'll suggest you clean up your code a bit. It looks a lot for a Notes App.
I started learning React not so long ago. Decided to make some kind of "life checklist" as one of my beginner projects. I have been using Functional Components in the core.
FYI:
I have data.js as an array of objects where "action", "emoji" and unique ID are stored.
I import it into my App.js.
const App = () => {
//Looping over data
const items = data.map((item) => {
return (
<ChecklistItem action={item.action} emoji={item.emoji} key={item.id} />
);
});
return (
<>
<GlobalStyle />
<StyledHeading>Life Checklist</StyledHeading>
<StyledApp>{items}</StyledApp>
<h2>Overall number: {data.length}</h2>
</>
);
};
export default App;
Here is my <ChecklistItem/> component:
const ChecklistItem = ({ action, emoji }) => {
//State
const [isActive, setIsActive] = useState(false);
//Event Handlers
const changeHandler = () => {
setIsActive(!isActive);
};
return (
<StyledChecklistItem isActive={isActive}>
<input type="checkbox" checked={isActive} onChange={changeHandler} />
<StyledEmoji role="img">{emoji}</StyledEmoji>
<StyledCaption>{action}</StyledCaption>
</StyledChecklistItem>
);
};
export default ChecklistItem;
I would be satisfied with the functionality so far, but I need to show how many "active" checklist items were chosen in the parent <App/> component like "You have chosen X items out of {data.length}. How can I achieve this?
I assume that I need to lift the state up, but cannot understand how to implement this properly yet.
You can do that by simply creating a state for storing this particular count of active items.
To do that, you would need to update your <App/> component to something like this
const App = () => {
const [activeItemsCount, setActiveItemsCount] = useState(0);
//Looping over data
const items = data.map((item, index) => {
return (
<ChecklistItem
key={index}
action={item.action}
emoji={item.emoji}
setActiveItemsCount={setActiveItemsCount}
/>
);
});
return (
<>
<h1>Life Checklist</h1>
<div>{items}</div>
<div>Active {activeItemsCount} </div>
<h2>Overall number: {data.length}</h2>
</>
);
};
export default App;
And then in your <ChecklistItem /> component, you would need to accept that setActiveItemsCount function so that you can change the state of the activeItemsCount.
import React, { useState, useEffect } from "react";
const ChecklistItem = ({ action, emoji, setActiveItemsCount }) => {
const [isActive, setIsActive] = useState(false);
const changeHandler = () => {
setIsActive(!isActive);
};
useEffect(() => {
if (!isActive) {
setActiveItemsCount((prevCount) => {
if (prevCount !== 0) {
return prevCount - 1;
}
return prevCount;
});
}
if (isActive) {
setActiveItemsCount((prevCount) => prevCount + 1);
}
}, [isActive, setActiveItemsCount]);
return <input type="checkbox" checked={isActive} onChange={changeHandler} />;
};
export default ChecklistItem;
By using the useEffect and the checks for isActive and 0 value, you can nicely increment or decrement the active count number by pressing the checkboxes.
How about this?
const data = [
{ action: '1', emoji: '1', id: 1 },
{ action: '2', emoji: '2', id: 2 },
{ action: '3', emoji: '3', id: 3 },
];
const ChecklistItem = ({ action, emoji, isActive, changeHandler }) => {
return (
<div isActive={isActive}>
<input type="checkbox" checked={isActive} onChange={changeHandler} />
<div>{emoji}</div>
<div>{action}</div>
</div>
);
};
const PageContainer = () => {
const [checkedItemIds, setCheckedItemIds] = useState([]);
function changeHandler(itemId) {
if (checkedItemIds.indexOf(itemId) > -1) {
setCheckedItemIds((prev) => prev.filter((i) => i !== itemId));
} else {
setCheckedItemIds((prev) => [...prev, itemId]);
}
}
const items = data.map((item) => {
const isActive = checkedItemIds.indexOf(item.id) > -1;
return (
<ChecklistItem
isActive={isActive}
changeHandler={() => changeHandler(item.id)}
action={item.action}
emoji={item.emoji}
key={item.id}
/>
);
});
return (
<div className="bg-gray-100">
<div>{items}</div>
<h2>
You have chosen {checkedItemIds.length} items out of {data.length}
</h2>
</div>
);
};
When data is used by a child component, but the parent needs to be aware of it for various reasons, that should be state in the parent component. That state is then handed to the child as props.
One way to do this would be to initialize your parent component with a piece of state that was an array of boolean values all initialized to false. Map that state into the checkbox components themselves and hand isActive as a prop based on that boolean value. You should then also hand the children a function of the parent that will change the state of the boolean value at a certain index of that array.
Here's a bit of a contrived example:
// Parent.tsx
const [checkBoxes, setCheckboxes] = useState(data.map(data => ({
id: data.id,
action: data.action,
emoji: data.emoji
isActive: false,
})));
const handleCheckedChange = (i) => {
setCheckboxes(checkBoxes => {
checkBoxes[i].isActive = !checkBoxes[i].isActive;
return checkBoxes;
})
}
return(
checkBoxes.map((item, i) =>
<ChecklistItem
action={item.action}
emoji={item.emoji}
key={item.id}
index={i}
isActive={item.isActive}
handleChange={handleCheckedChange}
/>
)
);
// CheckListItem.tsx
const CheckListItem = ({ action, emoji, index, isActive, handleChange }) => (
<StyledChecklistItem isActive={isActive}>
<input type="checkbox" checked={isActive} onChange={() => handleChange(index)} />
<StyledEmoji role="img">{emoji}</StyledEmoji>
<StyledCaption>{action}</StyledCaption>
</StyledChecklistItem>
)
Thanks to the community I resolved my dynamic id issue for the axios.get with ${this.props.match.params.id} and I can access my edit-form for each product.
Unfortunately this trick seems to be inefficient for the post request and I'm stuck. When I submit my form the axios.post in my handleSubmit deletes my previous data instead of updating with the new one. I can see that the sql request has undefined data and especially the id, I don't understand why..
I'm kind of a rookie in React, so could you suggest me how to fix my post request.
I provide you my edit-form, and some of the node back maybe it's relevant.
EditForm
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import axios from 'axios';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import Form from 'react-bootstrap/Form';
import Col from 'react-bootstrap/Col';
import FormControl from 'react-bootstrap/FormControl';
import Button from 'react-bootstrap/Button';
class EditForm extends React.Component {
constructor(props) {
super(props);
this.state = { product: [] };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
componentDidMount = () => {
axios
.get(`/products/edit-form/${this.props.match.params.id}`)
.then(response => {
console.log(response.data.products);
this.setState({
product: response.data.products
})
});
};
handleChange(e) {
this.setState({id: e.target.value})
this.setState({reference: e.target.value})
this.setState({designation: e.target.value})
}
handleSubmit(e) {
e.preventDefault();
const data = {
id: this.state.id,
reference: this.state.reference,
designation: this.state.designation
}
axios
.post(`/products/${data.id}`, data )
.then(res => console.log(res))
.catch(err => console.log(err));
};
renderForm() {
return this.state.product.map((product, index) => {
const { id,reference,designation } = product
return(
<>
<Form className="post" onSubmit={this.handleSubmit}>
<Form.Row>
<Form.Group as={Col} controlId="formGridReference">
<Form.Label>Reference</Form.Label>
<Form.Control type="text" value={reference}
onChange={this.handleChange} name="reference" />
</Form.Group>
<Form.Group as={Col} controlId="formGridDesignation">
<Form.Label>Designation</Form.Label>
<Form.Control type="text" value={designation}
onChange={this.handleChange} name="designation" />
</Form.Group>
</Form.Row>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</>
);
})
}
render() {
return (
<div>
<h1>Formulaire de modification</h1>
{this.renderForm()}
</div>
);
}
}
export default withRouter(EditForm);
Products
import React, { Component } from 'react';
import Table from 'react-bootstrap/Table';
import Button from 'react-bootstrap/Button';
import { Link } from 'react-router-dom';
import axios from 'axios';
const headings = [
'id','reference','designation'
];
export default class Products extends Component {
constructor(props) {
super(props);
this.state = {
products: []
};
};
componentDidMount = () => {
axios.get("/products").then(response => {
console.log(response.data.products);
this.setState({
products: response.data.products
})
});
};
renderTableHeader() {
return headings.map((key, index) => {
return <th key={index}>{key.toUpperCase()}</th>
})
}
renderProductData() {
return this.state.products.map((product, index) => {
const { id,reference,designation } = product
return (
<tr key={id}>
<td>
{id}
<Link to={`/edit-form/${id}`}>Modifier</Link>
</td>
<td>{reference}</td>
<td>{designation}</td>
</tr>
)
})
}
render() {
return (
<div>
<h1 id='title'>Produits</h1>
<Table striped bordered hover id='products'>
<thead>
{this.renderTableHeader()}
</thead>
<tbody>
{this.renderProductData()}
</tbody>
</Table>
</div>
);
}
}
App.js
class App extends Component {
render() {
return (
<React.Fragment>
<NavBar />
<Router>
<Route exact path="/" component={Products}/>
<Route path="/edit-form/:id" component={EditForm}/>
</Router>
</React.Fragment>
);
}
}
Node backend
//routes.js
// Get All
router.get('/products', getProducts.getProducts);
// Get sorted
// router.get('/products/:param', getProducts.getProductsSorted);
// Get single
router.get('/products/edit-form/:productId', getProducts.getProduct);
// Update
router.post('/products/:productId', getProducts.postProduct);
// productController.js
const getProduct = async (req, res) =>
{
const { productId } = req.params;
const product = await productDb.getProduct(productId);
res.status(200).send({ products: product.rows });
};
const postProduct = async (req, res) =>
{
const { productId } = req.params;
const { reference,designation } = req.body;
await productDb.updateProduct(productId, reference, designation);
res.status(200).send(`Le produit reference ${reference} a été modifié`);
console.log(`Le produit reference ${reference} a été modifié`);
// productDb.js
const getProduct = async (id) =>
{
const connection = new DbConnection();
return await connection.performQuery(`SELECT * FROM produits WHERE id=${id}`);
};
const updateProduct = async (id, reference, designation) =>
{
const connection = new DbConnection();
await connection.performQuery("UPDATE produits SET reference=?, designation=? WHERE id=?",
[reference, designation, id]);
};
Thank you
I would consider checking the state:
axios
.get(`/products/edit-form/${this.props.match.params.id}`)
.then(response => {
console.log(response.data.products);
this.setState({
product: response.data.products
})
});
This sets product as an array of products
handleChange(e) {
this.setState({id: e.target.value})
this.setState({reference: e.target.value})
this.setState({designation: e.target.value})
}
This sets state id, reference, designation - but note that it reads from the same target value - so if reference text field changes, it'll change id and designation to the same value as per #Asutosh's comment.
handleSubmit(e) {
e.preventDefault();
const data = {
id: this.state.product.id,
reference: this.state.product.reference,
designation: this.state.product.designation
};
axios
.post(`/products/${this.props.match.params.id}`, data )
.then(res => console.log(res))
.catch(err => console.log(err));
};
This reads from product, but product is an array. However, that doesn't reflect what handleChange is setting, which sets id, reference, designation in the root. That will cause id, reference, designation to be undefined, because this.state.product is an array.
A possible change that can be done is in handleChange:
const data = {
id: this.state.id,
reference: this.state.reference,
designation: this.state.designation
};
but that will only work if the user has changed something in the form. We need to also consider the fact the user might just click submit.
Also, I noticed another error (maybe unrelated? - read comments):
renderForm() {
return this.state.product.map((product, index) => {
const { id,reference,designation } = product // is this used?
return(
<>
<Form className="post" onSubmit={this.handleSubmit}>
<Form.Row>
<Form.Group as={Col} controlId="formGridReference">
<Form.Label>Reference</Form.Label>
{/* this should be reference instead of this.state.product.reference? why is it set as placeholder? */}
<Form.Control type="text" value={this.state.product.reference}
onChange={this.handleChange} name="reference" placeholder={reference} />
</Form.Group>
<Form.Group as={Col} controlId="formGridDesignation">
<Form.Label>Designation</Form.Label>
{/* this should be designation instead of this.state.product.designation? Why is designation set as a placeholder instead? */}
<Form.Control type="text" value={this.state.product.designation}
onChange={this.handleChange} name="designation" placeholder={designation} />
</Form.Group>
</Form.Row>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</>
);
})
}
In addition, if the goal is to submit changes based on a single product of products, I would consider creating a ProductsList component, which keeps componentDidMount, and then create a Product component which has the handleChange and handleSubmit
I have two React components, namely, Form and SimpleCheckbox.
SimpleCheckbox uses some of the Material UI components but I believe they are irrelevant to my question.
In the Form, useEffect calls api.getCategoryNames() which resolves to an array of categories, e.g, ['Information', 'Investigation', 'Transaction', 'Pain'].
My goal is to access checkboxes' states(checked or not) in the parent component(Form). I have taken the approach suggested in this question.(See the verified answer)
Interestingly, when I log the checks it gives(after api call resolves):
{Pain: false}
What I expect is:
{
Information: false,
Investigation: false,
Transaction: false,
Pain: false,
}
Further More, checks state updates correctly when I click into checkboxes. For example, let's say I have checked Information and Investigation boxes, check becomes the following:
{
Pain: false,
Information: true,
Investigation: true,
}
Here is the components:
const Form = () => {
const [checks, setChecks] = useState({});
const [categories, setCategories] = useState([]);
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
}
useEffect(() => {
api
.getCategoryNames()
.then((_categories) => {
setCategories(_categories);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
{categories.map(category => {
<SimpleCheckbox
label={category}
onCheck={handleCheckChange}
key={category}
id={category}
/>
}
)
}
const SimpleCheckbox = ({ onCheck, label, id }) => {
const [check, setCheck] = useState(false);
const handleChange = (event) => {
setCheck(event.target.checked);
};
useEffect(() => {
onCheck(check, id);
}, [check]);
return (
<FormControl>
<FormControlLabel
control={
<Checkbox checked={check} onChange={handleChange} color="primary" />
}
label={label}
/>
</FormControl>
);
}
What I was missing was using functional updates in setChecks. Hooks API Reference says that: If the new state is computed using the previous state, you can pass a function to setState.
So after changing:
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
}
to
const handleCheckChange = (isChecked, category) => {
setChecks(prevChecks => { ...prevChecks, [category]: isChecked });
}
It has started to work as I expected.
It looks like you're controlling state twice, at the form level and at the checkbox component level.
I eliminated one of those states and change handlers. In addition, I set checks to have an initialState so that you don't get an uncontrolled to controlled input warning
import React, { useState, useEffect } from "react";
import { FormControl, FormControlLabel, Checkbox } from "#material-ui/core";
import "./styles.css";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Form />
</div>
);
}
const Form = () => {
const [checks, setChecks] = useState({
Information: false,
Investigation: false,
Transaction: false,
Pain: false
});
const [categories, setCategories] = useState([]);
console.log("checks", checks);
console.log("categories", categories);
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
};
useEffect(() => {
// api
// .getCategoryNames()
// .then(_categories => {
// setCategories(_categories);
// })
// .catch(error => {
// console.log(error);
// });
setCategories(["Information", "Investigation", "Transaction", "Pain"]);
}, []);
return (
<>
{categories.map(category => (
<SimpleCheckbox
label={category}
onCheck={handleCheckChange}
key={category}
id={category}
check={checks[category]}
/>
))}
</>
);
};
const SimpleCheckbox = ({ onCheck, label, check }) => {
return (
<FormControl>
<FormControlLabel
control={
<Checkbox
checked={check}
onChange={() => onCheck(!check, label)}
color="primary"
/>
}
label={label}
/>
</FormControl>
);
};
If you expect checks to by dynamically served by an api you can write a fetchHandler that awaits the results of the api and updates both slices of state
const fetchChecks = async () => {
let categoriesFromAPI = ["Information", "Investigation", "Transaction", "Pain"] // api result needs await
setCategories(categoriesFromAPI);
let initialChecks = categoriesFromAPI.reduce((acc, cur) => {
acc[cur] = false
return acc
}, {})
setChecks(initialChecks)
}
useEffect(() => {
fetchChecks()
}, []);
I hardcoded the categoriesFromApi variable, make sure you add await in front of your api call statement.
let categoriesFromApi = await axios.get(url)
Lastly, set your initial slice of state to an empty object
const [checks, setChecks] = useState({});
I am trying to check the checkbox in componentDidUpdate by setting the "checked" to true but it's not working.
My State is stored in redux, I update the checkbox state in "onChange()" and in componentDidUpdate, I check if the state value is true or false based on which I am adding and removing the "checked" attribute. but this doesn't seem to work
import React, { Component } from "react";
import { saveOptions, getOptions } from '../api'
import { connect } from 'react-redux';
import { setUploadeSettings } from '../actions/settings'
import { Button, Checkbox, FormControl, TextField, withStyles } from '#material-ui/core/';
const styles = theme => ({
root: {
padding: theme.spacing(2)
},
button: {
marginTop: theme.spacing(1)
}
})
class UploadSettings extends Component{
async componentDidMount(){
const settingsFields = [...this.form.elements].map(i => i.name).filter(i => i)
let savedOptions = await getOptions( { option_names: settingsFields } )
savedOptions = savedOptions.data.data;
const reduxState = {}
savedOptions.forEach(i => reduxState[i.option_name] = i.option_value );
this.props.setUploadeSettings(reduxState)
}
componentDidUpdate(prevProps){
if(prevProps.uploadSettings !== this.props.uploadSettings){
[...this.form.elements].forEach(i => {
if(i.name === "convert_web_res")
this.props.convert_web_res ? i.setAttribute("checked", true) : i.removeAttribute('checked') //<- This Doesn't Seem to work
i.value = this.props.uploadSettings[i.name]
})
}
}
handleSubmit = async (e) => {
e.preventDefault();
try{
const formData = new FormData(e.target);
const elements = [...e.target.elements]
const eleIndex = elements.findIndex(i => i.name === 'convert_web_res')
const checked = elements[eleIndex].checked;
formData.set('convert_web_res', checked);
await saveOptions(formData)
} catch(e){
console.error(e)
}
}
render(){
const { classes, uploadSettings, setUploadeSettings } = this.props;
return(
<div className={classes.root}>
<form onSubmit={this.handleSubmit} ref={(form) => this.form = form}>
<FormControl>
<label>
<Checkbox
color="primary"
name="convert_web_res"
onChange={(e) => {
const state = uploadSettings;
state.convert_web_res = e.target.checked
setUploadeSettings(state)
}}
/> Convert Web Resolution
</label>
<TextField
defaultValue = {uploadSettings.resolution}
id="resolution"
name="resolution"
label="Resolution"
margin="normal"
/>
<TextField
defaultValue = {uploadSettings.dpi}
id="dpi"
name="dpi"
label="DPI"
margin="normal"
/>
<Button type="submit" variant="contained" color="primary" className={classes.button}>
Save
</Button>
</FormControl>
</form>
</div>
)
}
}
const mapStateToProps = state => {
return {
uploadSettings: state.settings.upload_settings
}
}
const mapDispatchToProps = dispatch => {
return {
setUploadeSettings: settings => dispatch(setUploadeSettings(settings))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(UploadSettings));
The Goal is to set the default value of the checkbox.
I tried adding the "checked" attribute directly on my checkbox component, Like so
<label>
<Checkbox
color="primary"
name="convert_web_res"
checked={uploadSettings.convert_web_res === "true" ? true : false}
onChange={(e) => {
const state = uploadSettings;
state.convert_web_res = e.target.checked
setUploadeSettings(state)
}}
/> Convert Web Resolution
</label>
this checks the checkbox but it gets frozen, User loses the ability to toggle the checkbox,
Use value and checked.
handleChange = event => {
// fire redux action
this.props.setUploadeSettings({ convert_web_res: event.target.checked });
};
<label>
<Checkbox
color="primary"
name="convert_web_res"
value={'Convert Web Resolution'}
checked={this.props.uploadSettings.convert_web_res}
onChange={(e) => this.handleChange(e)}
/> Convert Web Resolution
</label>