set Value of TextField on button click - reactjs

I am trying to set the value of TextField when a user clicks on a button.
The error I am getting is:
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
I think it has to do with the Button as I have a onclick function for each one. maybe there a better solution?
const [txtValue, setTxtValue] = useState({})
function campaignAmount(value){
// alert(value)
setTxtValue(value);
}
return (
<Grid container>
<Grid item lg={6}>
<ButtonGroup color="primary" aria-label="outlined primary button group">
<Button onclick={campaignAmount(300)}>$300</Button>
<Button onclick={campaignAmount(500)}>$500</Button>
<Button onclick={campaignAmount(1000)}>$1000</Button>
</ButtonGroup>
</Grid>
<Grid item lg={3}>
<TextField
id="campaignAmount"
name="campaignAmount"
margin="none"
fullWidth
value={`${txtValue[0]}`=== "undefined" ? '0' : `${txtValue[0]}`}
variant="outlined"
required={true}
/>
</Grid>
</Grid>
);
Update:
I have made some changes and now I am getting
Line 164:9: 'setTextValue' is not defined no-undef
Search for the keywords to learn more about each error.
New Code
const [txtValue, setTxtValue] = useState("0")
function schemaTypeSelectionHandle(event) {
// console.log('key: ', $(event.target).data('key'));
setTextValue(event.target.attributes.getNamedItem('data-key').value);
console.log('key: ', event.target.attributes.getNamedItem('data-key').value);
}
return (
<Grid container>
<Grid item lg={6}>
<ButtonGroup color="primary" onClick={this.schemaTypeSelectionHandle.bind(this)} aria-label="outlined primary button group">
<Button data-key='1'>$300</Button>
<Button data-key='1'>$500</Button>
<Button data-key='1'>>$1000</Button>
</ButtonGroup>
</Grid>
<Grid item lg={3}>
<TextField
id="campaignAmount"
name="campaignAmount"
margin="none"
fullWidth
value={`${txtValue[0]}`=== "undefined" ? '0' : `${txtValue[0]}`}
variant="outlined"
required={true}
/>
</Grid>
</Grid>
);

The edited code seems to be working fine. But the only issue is the little typo you have. It is "setTxtValue" not "setTextValue".
Your defined hook => const [txtValue, setTxtValue] = useState("0")

Related

How can I manually set accordion close on button

I am completely new to React. Here is the code I currently have. I removed some unnecessary parts to keep it clean.
<AccordionSummary
expandIcon={}
aria-controls="panel1a-content"
>This is Accordian
<AccordionSummary/>
<AccordionDetails>
<Grid container spacing={4} mb={5}>
<Grid item xs={12} md={6}>
<FormControl>
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={value}
onChange={handleChange}
>
<FormControlLabel
value="yes"
name="Yes"
control={<Radio onChange={handleChange} />}
label="Yes"
/>
<FormControlLabel
value="no"
name="No"
control={<Radio onChange={handleChange} />}
label="No"
/>
</RadioGroup>
</FormControl>
</Grid>
</Grid>
<Grid>
<Button className={classes.button_dark} variant="contained">
Submit
</Button>
<Button className={classes.button_light}>Cancel</Button>
</Grid>
</AccordionDetails>
I was using controlled accordion where I want a change, but I tried various combinations referring MUI docx, but I'm not getting any soln. This is the states I have used, but this one is for a radio button.
const [value, setValue] = React.useState("");
const handleChange = (e) => {
const {value} = e.target;
setValue(value);
};
What I want is that whenever I click the cancel button, the accordion should hide. The expand icon is working, but here I want to hide the accordion whenever I press the cancel button.
In MUI Accordion there's a property called expanded which accepts a boolean value and using that you can manually control the expansion and hide the according. You need to maintain a state to do that. Here's a basic example.
const [expanded, setExpanded] = React.useState();
<Accordion expanded={expanded === 'panel1'} onChange={() => setExpanded('panel1')}>
// items inside the accordion
<Button className={classes.button_light} onClick={() => setExpanded(undefined)}>Cancel</Button>
</Accordion>
This is just a simple solution to your problem.
refer to this for more details
Update
Here's a working example

React-hook-form + React-i18n = translation not working

I hope you are all good,
I have an object {valueA: "a", valueB: "b", ... } with a lot of fields and rather than writing all setter, you know:
const [valueX, setValueX] = useState(data.valueX?data.valueX:"")
I have been looking for some lazy solution so I find react-hook-form so, here is my code
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={2}>
{Object.keys(data).map((key) => (
<Grid item xs={10} sm={6} md={3} lg={2} key={key}>
<TextField
label={t(`docsInfo.${key}`)}
name={key}
defaultValue={data[key]}
variante="outlined"
{...register(key)}
/>
</Grid>
))}
</Grid>
<Grid mt={2}>
<Button
variant="contained"
endIcon={<UpgradeIcon />}
type="submit"
>
Update
</Button>
</Grid>
</form>
the code works fine it generates all the fields and the label with the first language (en) but when I click on the second one (jp) nothing happens (T_T)
I've checked my code to be sure my issue isn't something I am missing but could find anything wrong.
the translation module is in a context in my app refer to this
do you have any idea how I can solve my issue?
thanks...
are you sure that you have created the variables for the translation?

Multi-select text input on screen after closing modal

I have a modal and after I close the modal I want to show on the screen the options that were selected on the modal.
My code is here: https://codesandbox.io/s/react-select-xdpj7?file=/src/CreatableInputOnly.tsx
On this fragment below I am calling the part that handles the text on the modal on CreatableInputOnly. The part that handles the dropdown is on the ReactSelect call:
<Fragment>
<Button onClick={handleClickOpen}>ModalButton</Button>
<div>Selected options on the modal were: </div>
<Dialog
maxWidth={"sm"}
fullWidth={true}
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
classes={{
paperFullWidth: classes.paperFullWidth
}}
>
<DialogTitle id="alert-dialog-title">Dialog</DialogTitle>
<DialogContent
classes={{
root: classes.dialogContentRoot
}}
>
<Grid container spacing={2}>
<Grid item xs={6}>
<FormControl style={{ width: "100%" }}>
<ReactSelect isMulti={true} options={country} />
</FormControl>
</Grid>
</Grid>
<Grid container spacing={2}>
<CreatableInputOnly />
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} variant="contained">
Close
</Button>
</DialogActions>
</Dialog>
</Fragment>
You can create a state variable in the ModalTest.tsx and pass the setter function to the select component reactMaterialSelect.tsx.
const [selectedValues, setSelectedValues] = React.useState([]);
Then, you can update the code, which will display the selected options. Its just a simple map function printing a label of each index item.
<div>
Selected options on the modal were:{" "}
{selectedValues?.length
? selectedValues.map((item, idx) =>
idx !== 0 ? `, ${item.label}` : item.label
)
: ""}
</div>
Update the component part to send the additional prop of state setter value.
<ReactSelect
handleSelectValues={setSelectedValues}
isMulti={true}
options={country}
/>
In reactMaterialSelect.tsx, the change function are updated to change the state in the parent variable.
function handleChangeSingle(value) {
setSingle(value);
handleSelectValues([value]);
}
function handleChangeMulti(value) {
setMulti(value);
handleSelectValues(value);
}
To manage the createdInputs, a new state variable is added.
const [createAbleInputs, setCreateAbleInputs] = React.useState([]);
A variable to combine the results of both states.
const combinedArray =
createAbleInputs === null
? [...selectedValues]
: [...selectedValues, ...createAbleInputs];
Then the compoent createableInputsOnly is updated to change the state in the modal based on the changes in the component.
Updated sandbox link.

React Material Updating TextInput Value

So i'm trying basically to have a input field which completes a link and refers the user to it.
However when I click on the button I get a page to open properly but with a 'undefined' at the end as if the input field was not updated.
Any insight would be appreciated :)
let workerID;
const workerLink = "html link";
const workerSearch = workerLink + workerID
return (
<div className={classes.root}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Paper className={classes.paper}>
<h1><DashboardOutlinedIcon /> Job Card</h1>
<Moment className={classes.time}interval={1000} format="HH:mm:ss DD/MM/YYYY" />
</Paper>
</Grid>
<Grid item xs={4}>
<Paper className={classes.paper}>
<h3><AccessibilityNewRoundedIcon /> NameGet</h3>
<TextField id="standard-basic" label="Name:" variant="outlined" />
</Paper>
</Grid>
<Grid item xs={4}>
<Paper className={classes.paper}>
<h3>Fetch</h3>
<TextField id="standard-basic" label="ID:" variant="outlined" value={workerID}/>
<Button variant="contained" color="primary" className={classes.formstyle} value={workerID}>Search</Button><SearchRoundedIcon />
</Paper>
</Grid>
</Grid>
</div>
);
You should add a onChange attribute to the input(TextField in MaterialUI) and you are better using state in React instead of variables because if the variable updates again react will not update the UI with respect to the value of variable but it will update in case of state.
import React, {useState} from 'react'
// Your Rest of code
const [workerID, setWorkerID] = useState('')//initial value of workerID is empty string
return(
//Rest of Code
<TextField id="standard-basic" label="ID:" variant="outlined" value={workerID} onChange={event=>setWorkerID(event.target.value)}/>
//Rest of Code
)

Is it possible to make component style dependent on state without re-rendering?

I am working with the component below - I need the button to be contained when the filter state corresponds to it and outlined otherwise.
The way I do it now, the component re-renders every time the state is changed - I see why this is happening. However, I wonder if there would be a way to achieve the same functionality without referring to the filter state in this component? It is not a great user experience if the buttons disappear every time the state changes.
function FilterButtons({ filter, setFilter }) {
const classes = useStyles();
return (
<div className={classes.heroButtons}>
<Grid container spacing={2} justify="center">
<Grid item>
<Button
variant={filter === "All" ? "contained" : "outlined"}
color="primary"
onClick={() => setFilter("All")}
>
All
</Button>
</Grid>
<Grid item>
<Button
variant={filter === "Blue" ? "contained" : "outlined"}
color="primary"
onClick={() => setFilter("Blue")}
>
Blue
</Button>
</Grid>
<Grid item>
<Button
variant={filter === "Red" ? "contained" : "outlined"}
color="primary"
onClick={() => setFilter("Red")}
>
Red
</Button>
</Grid>
<Grid item>
<Button
variant={filter === "Green" ? "contained" : "outlined"}
color="primary"
onClick={() => setFilter("Green")}
>
Green
</Button>
</Grid>
</Grid>
</div>
);
}
You should have a look at styled components. This is exactly what you're describing in your question. You can pass a props to a styled components and it will use this props to update its style without rendering.

Resources