I have user data fetched from API, using Redux and I want to display it once component renders and also be able to update it. Currently I have initialValues in interface as:
const initialMultisportList = [
{
multisportType: {
package: '',
type: '',
cost: 0,
},
person: {
name: '',
lastName: '',
type: '',
cooperationForm: '',
},
firmCost: 0,
comment: '',
},
{
multisportType: {
package: '',
type: '',
cost: 0,
},
person: {
name: '',
lastName: '',
type: '',
cooperationForm: '',
},
firmCost: 0,
comment: '',
},
];
const multisportList is state from Redux where data is already fetched from API, it's array of objects.
const { multisportList } = useSelector((state: RootState) => state.employeeMultisport);
This is how I assign multisportList to initialValues.
const { values, handleChange, handleSubmit } = useFormik({
initialValues: multisportList.map((person) => ({
...person,
id: Math.random(),
})),
onSubmit: (values) => {
console.log('submitted');
displayParagraphHandler();
},
});
Below is example how I render two input fields
<StyledSection>
<h3>Benefit Systems</h3>
<form onSubmit={handleSubmit}>
{values.map((person, index) => {
return (
<StyledInputRow key={index}>
<FloatingLabel text="Name" name="Name">
<StyledInputText
id="name"
name="name"
value={values[index].person.name}
onChange={handleChange}
type="text"
/>
</FloatingLabel>
<FloatingLabel text="Last Name" name="Last Name">
<StyledInputText
id="lastName"
name="lastName"
value={values[index].person.lastName}
onChange={handleChange}
type="text"
/>
</FloatingLabel>
</StyledInputRow>
</form>
</StyledSection>
The problem is that all InputFields are empty, initialState is filled with const initialMultisportList , and it's not filled by multisportList. I also cannot update it. Once component is rendered I have also replaced values.map by multisportList.map but it also didn't work.
Can You please suggest how shall I correct my code to make it work ?
thanks
Related
I am trying to update my state from my react dynamically, this is my current state.
this.state = {
title: "",
image: "",
imageFile: "",
formTitle: "",
formMessage: "",
formImage: "",
Item: {
name: "Name",
price: "",
quantity: "",
discount: "",
shipping: "",
image: "",
formType: ""
}
}
How do I update in my Textbox dynamically instead of one by one?
setItemName = (name) => {
this.setState({
Item: {
...this.state.Item,
name
}
});
};
this is my attempt at solving this
and this is my Textbox using material UI
<TextField
className="my-24"
label="Item Name"
autoFocus
id="itemName"
name="itemName"
width={1}
value={this.state.Item.name}
onChange={this.setItemName}
variant="outlined"
/>
Thanks!!
As I understand from your doubt, you want to change the fields in state dynamically instead of writing the functions one by one....
setItemName = (changedValue, type) => {
this.setState({
Item: {
...this.state.Item,
[type]: changedValue
}
});
};
And your TextField going to be...
<TextField
className="my-24"
label="Item Name"
autoFocus
id="itemName"
name="itemName"
width={1}
value={this.state.Item.name}
onChange={(changedValue) => this.setItemName(changedValue, 'name')}
variant="outlined"
/>
You just need to pass the state field name in the setItemName argument.
As for 'price' you need to write setItemName(changedValue, 'price')
And nevermind,
I solve this,
This is my code for reference:
setItemValue = (field,value) => {
console.log(field,value)
this.setState(prevState => ({
Item: { // object that we want to update
...prevState.Item, // keep all other key-value pairs
[field] : value // update the value of specific key
}
}))
setItem = (key, value) => {
this.setState({
Item: {
...this.state.Item,
[key]: value
}
});
});
You can also try the following code
handleChange = e => {
this.setState({
Item: {
...this.state.Item,
[e.target.name]: e.target.value
}
});
Use name attribute as your state key :
<TextField
rowsMax={4}
placeholder="Enter name"
value={name}
name="name"
onChange={this.handleChange}
/>
I've 2 inputs and i want to post data in my api. how can I do with hooks?
I can post information of a single fields, but not in an array of objects
these are my inputs:
<TextField
name="material"
onChange={(e) => setProFields((prev) => ({
...prev,
[e.materiales_consumo.material]: e.target.value,
}))}
variant="outlined"
label="Material"
data-id={index}
type="text"
value={newPro.materiales_consumo[]}
/>
<TextField
name="magnitud"
onChange={(e) => setProFields((prev) => ({
...prev,
[e.materiales_consumo.magnitud]: e.target.value,
}))}
label="Magnitud"
variant="outlined"
data-id={index}
type="text"
value={newPro.materiales_consumo.magnitud}
In postman i post information like that:
{
"description":"//",
"family":"//",
"line":"//",
"model":"//",
"plz1":"//",
"plz2":"//",
"plz3":"//",
"materiales_consumo":[{"material":"String","magnitud":Number},
{"material":"String","magnitud":Number}]
}
And there is my state hook
const [newPro, setProFields] = useState({
description: '',
family: '',
line: '',
model: '',
plz1: '',
plz2: '',
plz3: '',
materiales_consumo: [],
});
I just started working with React and JSON and require some help. There is a textarea field in which a user enters some data. How to read row-wise the entered text as an array into a JSON variable of the request? Any assistance would be greatly appreciated.
The result I want is
{
id: 3,
name: 'Monika',
birthDay: '1999/01/01',
countryDTO: 'USA',
films: [
'Leon:The Professional',
'Star wars',
'Django Unchained',
],
} ```
My code:
import React from 'react';
import { Form, FormGroup, Label } from 'reactstrap';
import '../app.css';
export class EditActor extends React.Component {
state = {
id: '',
name: '',
birthDay: '',
countryDTO: '',
films: [],
}
componentDidMount() {
if (this.props.actor) {
const { name, birthDay, countryDTO, films } = this.props.actor
this.setState({ name, birthDay, countryDTO, films });
}
}
submitNew = e => {
alert("Actor added"),
e.preventDefault();
fetch('api/Actors', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: this.state.name,
birthDay: this.state.birthDay,
countryDTO: {
title: this.state.countryDTO
},
films: [{ title: this.state.films }]
})
})
.then(() => {
this.props.toggle();
})
.catch(err => console.log(err));
this.setState({
id: '',
name: '',
birthDay: '',
countryDTO: '',
films: ''
});
}
onChange = e => {
this.setState({ [e.target.name]: e.target.value })
}
render() {
return <div>
<table>
<tr>
<td colspan="2">
<h3> <b>Add actor</b></h3>
<FormGroup>
<Label for="id">Id: </Label>
<input type="text" name="id" onChange={this.onChange} value={this.state.id} /><p />
<Label for="name">Name:</Label>
<input type="text" name="name" onChange={this.onChange} value={this.state.name} /><p />
<Label for="birthDay">Birth day:</Label>
<input type="text" name="birthDay" onChange={this.onChange} value={this.state.birthDay} placeholder="1990/12/31" /><p />
<Label for="country">Country:</Label>
<input type="text" name="countryDTO" onChange={this.onChange} value={this.state.countryDTO} /><p />
<Label for="Films">Films:</Label>
<textarea name="films" value={this.state.films} onChange={this.onChange} /><p />
</FormGroup>
</td>
</tr>
<tr>
<td>
<Form onSubmit={this.submitNew}>
<button class="editButtn">Enter</button>
</Form>
</td>
</tr>
</table >
</div>;
}
}
export default EditActor;
If you change the below code it will work automatically.
State declaration
this.state = {
name: 'React',
films:["Palash","Kanti"]
};
Change in onechange function
onChange = e => {
console.log("values: ", e.target.value)
this.setState({ [e.target.name]: e.target.value.split(",") })
}
change in textarea
<textarea name="films" value={this.state.films.map(r=>r).join(",")} onChange={this.onChange} />
Code is here:
https://stackblitz.com/edit/react-3hrkme
You have to close textarea tag and the following code is :
<textarea name="films" value={this.state.films} onChange={this.onChange} >{this.state.films}</textarea>
My understanding of your problem is that you would like to have each line in the text area dynamically added as an entry in the films array. This can be achieved as follows:
import React, { Component } from "react";
export default class textAreaRowsInState extends Component {
constructor(props) {
super(props);
this.state = {
currentTextareaValue: "",
films: []
};
}
handleChange = e => {
const { films } = this.state;
const text = e.target.value;
if (e.key === "Enter") {
// Get last line of textarea and push into films array
const lastEl = text.split("\n").slice(-1)[0];
films.push(lastEl);
this.setState({ films });
} else {
this.setState({ currentTextareaValue: text });
}
};
render() {
const { currentTextareaValue } = this.state;
return (
<textarea
defaultValue={currentTextareaValue}
onKeyPress={this.handleChange}
/>
);
}
}
Keep in mind that this method is not perfect. For example, it will fail if you add a new line anywhere other than at the end of the textarea. You can view this solution in action here:
https://codesandbox.io/s/infallible-cdn-135du?fontsize=14&hidenavigation=1&theme=dark
change textarea() tag
to
<textarea name="films" value={this.state.films} onChange={this.onChange} >{this.state.films}</textarea>
You can use split() :
films: {this.state.films.split(",")}
Normally in HTML you do something like this:
<form>
<input type="text"/>
<input type="text"/>
<input type="submit"/>
</form>
I believe this is not the React way to do it.
Another way to do like i did in my app, is not the best way to do as well i believe.
Like this:
buttonclickRequest(){
var reasonn = document.getElementById("testControl").value;
}
<div>
<FormControl id="testControl"/>
<Button id="btnRequest" onClick={this.buttonclickRequest}/>
</div>
In other stackoverflow topics I saw examples like this:
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
place: '',
address: '',
email: '',
phoneNumber: ''
};
}
handleClick() {
//do something
}
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value
})
}
<div>
<input type="text" onChange={e => this.handleChange(e)}/>
<button type="submit" onClick={this.handleClick}/>
</div>
But i have my questions at this point as well,
I don't know how to do this properly with multiple text inputs:
You can make multiple specific changehandlers which is inefficiƫnt,
You can make a changehandler with a switch to set the properties
Is it even efficient to do a handle change on the inputfields? Because I just want the inputfield values when the button is clicked..
This is the form I'm talking about.
So how to properly get the multiple input data with React, when the button is clicked?
Thanks for your help in advance!
I think first you should add name attribute to your input field and use the name to set the state and then use the state on handleClick:
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
place: '',
address: '',
email: '',
phoneNumber: ''
};
}
handleClick = () => {
//do something
console.log(this.state);
// should be something like this {
// firstName: '',
// lastName: '',
// place: '',
// address: '',
// email: '',
// phoneNumber: ''
//}
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
render() {
return(
<div>
<input type="text" name="firstName" onChange={this.handleChange}/>
<input type="text" name="lastName" onChange={this.handleChange}/>
<button type="submit" onClick={this.handleClick}/>
</div>
)
}
Note that the name should match the state key.
Assuming you may be looking for state values
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
place: '',
address: '',
email: '',
phoneNumber: ''
};
}
handleClick() {
console.log("State ==>", this.state);
}
setFirstName = (e) => {
this.setState({
firstName: e.target.value
})
}
setPhoneNumber = (e) => {
this.setState({
phoneNumber: e.target.value
})
}
render(){
return('
<div>
<label> First Name </label>
<input type="text" name="firstName" onChange={e => this.setFirstName(e)}/>
<label> Phone Number </label>
<input type="text" name="phoneNumber" onChange={e => this.setPhoneNumber(e)}/>
<button type="submit" onClick={this.handleClick}/>
</div>
')
}
and yes... you are right creating change handlers for each input its not efficient on your case, what you need is a react form that gives you the old and submit options,you cant use old form because it needs to update the page to retrieve the values.
I Suggest you to use Antd form witch gives you all in components, i even suggest you to use their Input components witch look very nice and handles pretty well.
Antd Design (User interface components for react) - Antd
some sample code.
give it a try !!! CodeSandbox
I am attempting to create an edit form in React. I can successfully query my database and can see the data is what is expected after my get request. I then want to set the state of various properties on my component so it fills in my form, which I can then edit.
Here is my react component
constructor(props) {
super(props);
this.state = {
name: '',
teamName: '',
bio: '',
teamId: '',
uploadedFileCloudinaryUrl: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.findPlayerById(this.props.params.id)
}
findPlayerById(playerId) {
axios.get("/api/player/" + playerId)
.then(res => {
const player = res.data;
console.log(player);
this.setState({
name: player.name,
teamName: player.teamName,
bio: player.bio,
teamId: player.teamId,
uploadedFileCloudinaryUrl: player.profileImageUrl
});
});
}
And here is my rendered HTML
<div className="form-group">
<label className="control-label">Name</label>
<input type="text" className="form-control" ref="name"
defaultValue={this.state.name}
onChange={this.handleChange.bind(this, 'name')}/>
</div>
I don't get any errors but I don't think the state is being correctly set within my promise. Am I doing something wrong?