Submitting form with textarea in React - javascript

I have a textarea that I want to stringify to JSON on form submission. I will even settle for just having the function set the textarea value.
import React from 'react';
export default class ClinicalMain extends React.Component {
constructor(props) {
super(props);
}
state = {selectedOption: ''}
// my function to update the textarea
reactStringify() {
let obj = {
name: "bob",
age: 4
}
console.log('in stringify');
let value = JSON.stringify(obj);
}
componentDidMount() { }
render() {
return (
<React.Fragment>
<form>
<button type="button"
onClick={this.reactStringify}
id="reactid"
>React stringify</button>
<textarea value={this.value}
defaultValue=""
rows="10" cols="80"
></textarea>
<br />
</form>
</React.Fragment>
)
}
}
let value does not update. Do I need to use setState? this?

There are a number of issues in the code indicating a lack of familiarity with the excellent React tutorial. As with any library, it's necessary to spend time reading the manual before diving in.
State should not be modified directly. Use this.setState() to replace state. this.setState() doesn't work instantly; it simply informs the React library that the state needs updating and React handles the update on its own when it sees fit.
Beyond this, let value = ... is a purely local variable, not a class variable, so this.value would be undefined in render no matter what; in other words, your code doesn't attempt to modify or access state in any way.
Class functions that attempt to access this need to be bound. For example, onClick={this.reactStringify} passes a reference to the this.reactStringify function, but this will be undefined inside of this.reactStringify unless an arrow function is used (which implicitly binds this), or this is explicitly bound:
this.handleChange = this.handleChange.bind(this);
Explicit is considered to be better practice for class components than the arrow function approach because it only requires one call to bind when the component is constructed.
React typically uses something called controlled components to listen to changes on a text field. This means that the element's value tracks component state and acts as the single source of truth.
While I'm not exactly sure what you're ultimately looking to accomplish, here's a working example to get you moving again which demonstrates the above concepts.
class ClinicalMain extends React.Component {
constructor(props) {
super(props);
this.state = {value: "", output: ""};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange({target: {value}}) {
this.setState(() => ({value}));
}
handleSubmit(e) {
e.preventDefault();
this.setState(state => ({
output: `you wrote: "${state.value}"`
}));
}
render() {
return (
<React.Fragment>
<form onSubmit={this.handleSubmit}>
<textarea
value={this.state.value}
onChange={this.handleChange}
></textarea>
<div>
<input type="submit" value="Show output" />
</div>
</form>
<div>{this.state.output}</div>
</React.Fragment>
);
}
}
ReactDOM.createRoot(document.querySelector("#app"))
.render(<ClinicalMain name="World" />);
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div id="app"></div>
Here are relevant sections of the documentation which provide more detail:
State and Lifecycle
Handling Events
Forms

Related

How can I make the default value of an input changeable in ReactJS?

I am new to working with React so this might be an easy one that I am struggling to figure out. Let's say I have this very simple class, that renders an input with a default value. I want this input to have the value I set it, but also being able to change it. However, when it renders, the input field is filled with "hi" and I can't write or delete anything over it. How can I make this possible?
export class Hello extends React.Component {
render(){
let i = "hi"
return(
<div>
<input type="input" value={i} />
</div>
);
}
}
Store the input value as part of your component's state, and listen for the onchange event on the input field to update the component's state.
export class Hello extends React.Component {
state = {
textbox: "hi",
};
render() {
return(
<div>
<input
type="input"
value={this.state.textbox}
onChange={ev => this.setState({ textbox: ev.target.value })}
/>
</div>
);
}
}
See examples: https://reactjs.org/docs/forms.html#controlled-components
You need to use state for this purposes. Look here: https://reactjs.org/docs/forms.html#controlled-components
I'am adding a bit different answer, its depends if your component is Controlled or Uncontrolled component, see difference in docs.
Controlled example you can find in other answers or docs.
Uncontrolled example is usually when using <form/> elements, in this case you can just add defaulValue prop as mentioned in related docs.
class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" defaultValue="hi" ref={this.input} />
<input type="submit" value="Submit" />
</form>
);
}
}

Is it bad practice to only use props in child components? Child components without own state

I'm developing an application and all the child components that I have developed don't jave their own state. If not, it's the parent container that passes the state through props and the children modify the props through callbacks. I know that it is normal for simple components, but I have made some component a little more complex without state, and I do not know if it is bad practice. I give an example, although it does not make much sense, to see that the child has logic and modifies the props but does not have its own state.
Parent component
class Form extends React.Component {
constructor(){
super();
this.state = {
person: {
name: 'Jonh',
surname: 'Bold',
money: 20
},
expenses: 0
}
this.handleChangePerson = this.handleChangePerson.bind(this);
this.handleChangeExpenses = this.handleChangeExpenses.bind(this);
}
handleChangePerson(value){
this.setState({person: {...this.state.person, ...value }})
}
handleChangeExpenses(event){
this.setState({expenses: event.target.value })
}
render() {
return (
<div>
<h1>Personal Information</h1>
<PersonalInformation person={this.state.person} expenses={this.state.expenses} handleChange={this.handleChangePerson} />
<h1>Expenses</h1>
<input type="number" name="expenses" onChange={this.handleChangeExpenses} />
<h1>Total money: {this.state.person.money} </h1>
</div>)
}
};
Child component
class PersonalInformation extends React.Component {
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
}
componentDidUpdate(prevProps){
if(prevProps.expenses !== this.props.expenses){
this.props.handleChange({money: this.props.person.money - this.props.expenses})
}
}
handleChange(){
let {name, value} = event.target;
if(name === 'money'){
value = parseInt(value, 10);
value = value >= 100 || value < 0 ? 99 : value
}
this.props.handleChange({ [name]: value})
}
render() {
return (
<div>
<p>Name: <input type="text" name="name" value={this.props.person.name} onChange={this.handleChange} /></p>
<p>Surname: <input type="text" name="surname" value={this.props.person.surname} onChange={this.handleChange} /></p>
<p>Money: <input type="number" name="money" value={this.props.person.money} onChange={this.handleChange} /></p>
</div>)
}
};
Maybe it is not the best example, but what I want to show is whether it is bad practice or not to have slightly complex child components without state that modify the state of the parent.Or it is better to have a component with its own state that does not directly modify the parent.
Thanks!
No it is not bad.
And sometimes it is the simplest way of doing.
Another approaches would involve either a Context: https://reactjs.org/docs/context.html
or Redux: https://redux.js.org/api/api-reference
No, props are made to pass the props from the parent component to childs.
The class components are essential and it's good to have and working with them, But just try to optimize your code readability and manipulation by learning/using functionnal components with hooks, they are much easier and don't have the confusion with the this keyword.

Parent State not updating when passed data from child component

I'm trying to create a note-taking application in React.
The application should add a new note when an "Add note" button is pressed with the value in the input box.
Unfortunately when I try to push the note to the list and update the parents state the changes aren't reflected on screen or in the react debugger.
The pushing of new note to list can be seen in the alert line but not anywhere else.
Here is the parent component containing the original notes state:
class NoteApplication extends React.Component {
constructor(props) {
super(props);
this.state = {
notes: Array(),
};
this.update = this.update.bind(this);
this.state.notes.push("Sample note");
}
update(notes) {
return () => {
this.setState({
notes: notes
});
}
}
render() {
return (
<div>
<h1>React Notes</h1>
<div class="InsertBarDiv">
<InsertBar
notes={this.state.notes}
update = {this.update}
/>
</div>
<div class="NotesDiv">
<Notes
notes={this.state.notes}
/>
</div>
</div>
)
}
}
And here is the child component
class InsertBar extends React.Component {
constructor(props) {
super(props);
this.state = {value:''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
const notes = this.props.notes.slice();
notes.push(this.state.value);
this.props.update(notes);
alert(notes);
event.preventDefault();
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input class="noteInsertBar" type="text" name="" onChange={this.handleChange}/>
<input class="insertBut" type="submit" value="Add Note"/>
</form>
</div>
)
}
}
class Notes extends React.Component {
renderNote(i) {
return (
<div>
{this.props.notes}
</div>
)
}
render() {
return (
<div>
<h2>Notes:</h2>
<div class="FullNote">
{this.renderNote(1)}
</div>
</div>
)
}
}
I would expect the note to be pushed to the copy of the notes list & the parents state to be set to the new copy of the notes list.
I would then expect this to be displayed onscreen.
It's likely due to the fact that you're returning a function from update, you should just call setState when update gets called:
update(notes) {
setState({ notes });
}
Side note: You should avoid Array.push when dealing with arrays in React. The way you're doing it is fine because you're calling slice to copy the array before you push, but if you use concat or the spread operator, you'll be less likely to unintentionally introduce bugs.
const notes = this.props.notes.concat(this.state.value);
or:
const notes = [...this.props.notes, this.state.value];
I got some help in the react discord thanks to the user #WasaWasaWassup so I'd like to share what fixed my issue.
Mutating the parent state in the constructor to add a sample note was causing issues.
The second issue was my update function returning a function yet being called as if it wasn't.
Removing the constructor mutating & altering my update function to just set the state without an embedded function fixed all my issues and the notes array updates and displays correctly.

React input binding to state vs local variable

I am looking at a tutorial for binding input in react with state. What I don't understand is why do I need to bind it to the state vs just a local vairable since it won't cause renders.
In my case I have a login form, in the tutorial it is sending message form. The idea is that the value is send to the App.js(parent) on submit using inverse data flow. It looks like this:
class Login extends Component{
constructor(){
super()
this.state = {
username: ''
};
this.login = this.login.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
this.setState({
username: e.target.value
});
}
//here I make a post request and then I set the user in app.js
handleSubmit(e) {
e.preventDefault();
fetch('http://localhost:8080/login', {
method: 'post',
body: JSON.stringify(username)
}).then(data => data.json())
.then(data => {
this.props.setUser(data)
this.setState({
username: ''
})
}
}
render(){
return (
<section>
<form onSubmit={this.submit}>
<input placeholder="username"
onChange={this.changeInput} type="text"
value={this.state.username}/>
</form>
</section>
)
}
Is there a reason to use setState vs just a local variable which won't cause a rendering?
You don't have to, you could make it work without ever storing username in the state. All you have to do is listen for a submit event and fetch the input value at that time, using a ref.
class Login extends Component {
handleSubmit(e) {
e.preventDefault();
console.log(this.refs.username.value)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input ref="username" type="text" />
<button type="submit">Submit</button>
</form>
);
}
});
However the usual way to do that with React is to store the input value in the state and update the state every time the value change. This is called a controlled component and it ensures that the input value and the state are always consistent with each other.
class Login extends Component {
constructor() {
super()
this.state = {
username: ''
};
}
handleChange(e) {
this.setState({
username: e.target.value
});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input onChange={e => this.setState({ username: e.target.value })} type="text" value={this.state.username} />
<button type="submit">Submit</button>
</form>
</div>
)
}
}
Among other things, it makes things easier to validate the input value or modify it if you need. For instance, you could enforce uppercase by converting the state to uppercase whenever the state changes.
The value of the input field has to change to the new value, that is why for the on change event you set the state to the next event value. If you don't set state, the value will be the same even though it is entered by user.
Hope this helps,
Happy Learning.

Managing large forms - ReactJS

I was reading about react forms, and I just can read about two ways of managing data in forms.
The first one - refs, putting refs in each data input:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in this.textInput.
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
and the second one Controlled Forms, putting a handler for each data input:
import React, { Component } from 'react';
import Form from 'react-form-controlled';
export default class Example extends Component {
constructor(props, context) {
super(props, context);
this.state = {
users: [{
firstName: 'Zlatko'
}, {
firstName: 'Livia'
}]
};
}
onChange = (data) => {
this.setState(data);
}
onSubmit = (data) => {
alert(`Hi ${data.users[0].firstName}`);
}
render() {
return (
<Form
value={this.state}
onChange={this.onChange}
onSubmit={this.onSubmit}
>
<fieldset name="users">
<label>
<input name="firstName" />
</label>
</fieldset>
<button type="submit">Submit</button>
</Form>
);
}
}
So, imagine you have a large form with a lot of data input, will you have to declare all the handler functions for each input in the form? (also, the total of bindings in the constructor)
Wouldn't it be convenient to just submit a just read form.input1, form.input2? I mean, somehing like this:
onSubmit(formValues){
payload = [
{'value1': formValues.input1 },
{'value2': formValues.input2 },
...
{'valueN': formValues.inputN },
]
}
without going to reading it from state?
I any case, is it and advantage to have a smart component with a lot of handlers for managing form values? or maybe the other approach, having a refs for each component in the form?
I would suggest to check redux + redux-form combo. Managing form state with these modules is piece of case. You can have functional components without any local state or handlers.

Categories

Resources