i'm building basic chat app with react, and i had many of SO form submit questions and answers but none are helped me, i know it may be dumb type question but really i'm stucked here, any helps are thank you, below is my code.
export default class Call extends Component {
state = {
Message:''
};
onChange = e => {
let { Message, value } = e.target;
console.log(e.target.value); // here i'm getting input value
this.setState({ [Message]: value });
};
onSubmit = e => {
e.preventDefault();
console.log("Message is ", this.state.Message); //getting undefined
};
render() {
return (
<form onSubmit={this.onSubmit}>
<input type="text" name="Message" onChange={this.onChange}/>
<input type="submit" value="Send" />
</form>
)}
Try without brackets:
onChange = e => {
let { Message, value } = e.target;
console.log(e.target.value); // here i'm getting input value
this.setState({ Message: value });
};
You need to initialize state inside class constructor and set it using this.setState({ Message: value }) syntax.
class Call extends React.Component {
constructor(props) {
super(props);
this.state = {
Message: ''
};
}
onChange = e => {
let { value } = e.target;
console.log(e.target.value); // here i'm getting input value
this.setState({ Message: value });
};
onSubmit = e => {
e.preventDefault();
console.log("Message is ", this.state.Message); //getting undefined
};
render() {
return (
<form onSubmit={this.onSubmit}>
<input type="text" name="Message" onChange={this.onChange} />
<input type="submit" value="Send" />
</form>
);
}
}
ReactDOM.render(<Call />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Related
I don't think I missed anything in making the form a controlled component. Why doesn't the state doesn't change as characters are being input?
class AddChores extends Component {
state = {
chore: "",
};
handleChange = (evt) => {
this.setState({ chore: evt.target.value });
};
handleSubmit = (evt) => {
evt.preventDefault();
this.props.addChores(this.state);
this.setState({ chore: "" });
};
render() {
console.log(this.state);
return (
<div>
<form onClick={this.handleSubmit}>
<input
type="text"
placeholder="New Chore"
value={this.state.chore}
onChange={this.handleChange}
/>
<button className="button">ADD CHORE</button>
</form>
</div>
);
}
}[![React dev tool showing no simultaneous update][1]][1]
I made some changes as below and it works fine for me. Hope it helps you too.
class AddChores extends Component {
constructor(props) {
super(props);
this.state = {
chore: ""
};
}
handleChange = (event) => {
this.setState({
chore: event.target.value
});
};
handleSubmit = (evt) => {
evt.preventDefault();
// this.props.addChores(this.state);
this.setState({ chore: "" });
};
componentDidUpdate(){
console.log('the state', this.state.chore)
}
render() {
return (
<div>
<form onClick={this.handleSubmit}>
<input
type="text"
placeholder="New Chore"
value={this.state.chore}
onChange={this.handleChange}
/>
</form>
</div>
);
}
}
not sure why is this happening but try using the second form of setState
this.setState(() => ({ chore: evt.target.value}))
check this https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
My first React session data storage, so thanks. I am trying to set up inputing data and then placing it in session storage, so it can be edited, viewed or deleted later. There are 2 pieces of data, "title" and "note" to be inputed into a form. Nothing happens when I type into the form inputs. Any other help welcome also.
class AddNote extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
content: ''
}
}
componentDidMount() {
this.getFormData();
}
//let notes = getSessionItem(keys.notes);
//if (!notes) { notes = ""; }
onTitleChange(event) {
this.setState({ title: event.target.value }, this.storeFormData);
this.storeFormData();
}
onContentChange(event) {
this.setState({ content: event.target.value }, this.storeFormData);
}
storeFormData() {
const form = {
title: this.state.title,
content: this.state.content
}
setSessionItem(keys.user_form, form);
}
getFormData() {
const form = getSessionItem(keys.user_form);
if (form) {
this.setState({
title: form.name,
content: form.content
});
}
}
render() {
return (
<div>
<div>
<h2>ADD NOTE PAGE</h2>
</div>
<form classname="nav1">
<div>
<label><b>Title</b></label>
<input type="text"
value={this.state.title}
onchange={this.onTitleChange.bind(this)}
/>
</div>
<div>
<label><b>Content</b></label>
<input type="text"
value={this.state.content}
onchange={this.onContentChange.bind(this)}
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
}
}
export default AddNote;
and the storage file:
export const keys = {
title: 'title',
notes: 'notes'
}
export const getSessionItem = function (key) {
let item = sessionStorage.getItem(key);
item = JSON.parse(item);
return item;
}
export const setSessionItem = function (key, value) {
value = JSON.stringify(value);
sessionStorage.setItem(key, value);
}
export const removeSessionItem = function (key) {
sessionStorage.removeItem(key);
}
No need to have 2 change handler for your input. You can do it using a common change handler.
<form classname="nav1">
<div>
<label><b>Title</b></label>
<input type="text"
value={this.state.title}
name="title" <---- Provide name here
onChange={this.onChange}
/>
</div>
<div>
<label><b>Content</b></label>
<input type="text"
value={this.state.content}
name="content" <---- Provide name here
onChange={this.onChange}
/>
</div>
<button type="submit">Submit</button>
</form>
Your onChange function should be, and use callback in setState to call your storeFormData function.
onChange = (e) => {
this.setState({
[e.target.name] : e.target.value
}, () => this.storeFormData())
}
Note: In React we use camelCase, for example, onchange should be onChange and classname should be className.
Also make sure you bind this to storeFormData and getFormData functions, or you can use arrow function's to automatically bind this.
Demo
Every time I click the button a post is being created and displayed
But the input data isn't showing up
import React, { Component } from 'react'
export default class App extends Component {
state = {
dataArr : [],
isClicked: false,
title : '',
img : ''
}
handleSubmit = (e) => {
e.preventDefault()
}
handleChange = (e) => {
[e.target.name] = e.target.value
}
handleClick = () => {
const copyDataArr = Object.assign([], this.state.dataArr)
copyDataArr.push({
title : this.state.title,
img : this.state.img
})
this.setState({
isClicked : true,
dataArr : copyDataArr
})
}
render() {
console.log(this.state.title)
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type="text" name="title" placeholder="Title.." onChange={this.handleChange}/>
<input type="text" name="img" placeholder="Image.." onChange={this.handleChange}/>
<button onClick={this.handleClick}>SUBMIT</button>
</form>
{ this.state.isClicked ?
this.state.dataArr.map(
(post, index) => {
return(
<div class="div">
<h1>title: {post.title}</h1>
<img src={post.img} alt="ohno"/>
</div>
)
}
)
: null }
</div>
)
}
}
Created an empty array on state and copied the array and pushed in the input values. What am I doing wrong?
Need the onChange to work and the input data to display
Trying to learn forms in react. Hope someone can help out
Your handleChange function is not updating state with the data you enter to the inputs. Looks like you might have forgotten to call this.setState(). Try this
:
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
Also here is a sandbox with the working code: https://codesandbox.io/s/distracted-darkness-xp3nu
You have to add a value attribute to the input tag and pass the state value.
<input type="text" name="title" value={this.state.title} placeholder="Title.." onChange={this.handleChange}/>
Your handle change function should be as follows
handleChange = (e) => {
this.setState({[e.target.name] : e.target.value});
}
I'm trying to pass 2 elements within the todo array, however it just returns the term element value. I see no error in the console.
It seems that the
items: [...this.state.items, this.state.term, this.state.name ]
only accepts two parameters.
I'm currently following this
https://reactjs.org/docs/handling-events.html
const { Component } = React;
class App extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
name: '',
items: []
};
}
onChange = (event) => {
this.setState({name: event.target.value, term: event.target.value});
}
onSubmit = (event) => {
event.preventDefault();
this.setState({
term: '',
name: '',
items: [
...this.state.items,
this.state.term,
this.state.name
]
});
}
render() {
return (
<div>
<form className="App" onSubmit={this.onSubmit}>
<input value={this.state.term} onChange={this.onChange}/>
<input value={this.state.name} onChange={this.onChange}/>
<button>Submit</button>
</form>
<pre>{JSON.stringify(this.state.items)}</pre>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I suspect the issue you're asking about is the fact that your onChange event updates both term and name and whatever you type into one input goes into the other. Here's how you can resolve that:
Add a name attribute to your input that corresponds to the key in the state.
Access the value of name in onChange and update the value accordingly.
Solution
const { Component } = React;
class App extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
name: '',
items: []
};
}
onChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
}
onSubmit = (event) => {
event.preventDefault();
this.setState({
term: '',
name: '',
items: [
...this.state.items,
this.state.term,
this.state.name
]
});
}
render() {
return (
<div>
<form className="App" onSubmit={this.onSubmit}>
<input name="term" value={this.state.term} onChange={this.onChange}/>
<input name="name" value={this.state.name} onChange={this.onChange}/>
<button>Submit</button>
</form>
<pre>{JSON.stringify(this.state.items)}</pre>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I dont think your this.setState has any issue for your example.
You seem to be using this.onChange wrong.
I changed its implementation so that both input can have their own respective handler.
onChange = key => event => {
this.setState({ [key]: event.target.value }); };
Also changed input callbacks to pass key value from the render function below.
render() {
const { term, name, items } = this.state;
return (
<div>
<form className="App" onSubmit={this.onSubmit}>
<input value={term} onChange={this.onChange('term')} />
<input value={name} onChange={this.onChange('name')} />
<button>Submit</button>
</form>
{items.join(", ")}
</div>
);
}
}
Your prior code was problematic which was rendering same value for name and term with whatever you type in any of your input boxes.
I'm trying to disable a button when an input field is empty. What is the best approach in React for this?
I'm doing something like the following:
<input ref="email"/>
<button disabled={!this.refs.email}>Let me in</button>
Is this correct?
It's not just duplication of the dynamic attribute, because I'm also curious about transferring/checking the data from one element to another.
You'll need to keep the current value of the input in state (or pass changes in its value up to a parent via a callback function, or sideways, or <your app's state management solution here> such that it eventually gets passed back into your component as a prop) so you can derive the disabled prop for the button.
Example using state:
<meta charset="UTF-8">
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<div id="app"></div>
<script type="text/jsx;harmony=true">void function() { "use strict";
var App = React.createClass({
getInitialState() {
return {email: ''}
},
handleChange(e) {
this.setState({email: e.target.value})
},
render() {
return <div>
<input name="email" value={this.state.email} onChange={this.handleChange}/>
<button type="button" disabled={!this.state.email}>Button</button>
</div>
}
})
React.render(<App/>, document.getElementById('app'))
}()</script>
Using constants allows to combine multiple fields for verification:
class LoginFrm extends React.Component {
constructor() {
super();
this.state = {
email: '',
password: '',
};
}
handleEmailChange = (evt) => {
this.setState({ email: evt.target.value });
}
handlePasswordChange = (evt) => {
this.setState({ password: evt.target.value });
}
handleSubmit = () => {
const { email, password } = this.state;
alert(`Welcome ${email} password: ${password}`);
}
render() {
const { email, password } = this.state;
const enabled =
email.length > 0 &&
password.length > 0;
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Email"
value={this.state.email}
onChange={this.handleEmailChange}
/>
<input
type="password"
placeholder="Password"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
<button disabled={!enabled}>Login</button>
</form>
)
}
}
ReactDOM.render(<LoginFrm />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<body>
</body>
Another way to check is to inline the function, so that the condition will be checked on every render (every props and state change)
const isDisabled = () =>
// condition check
This works:
<button
type="button"
disabled={this.isDisabled()}
>
Let Me In
</button>
but this will not work:
<button
type="button"
disabled={this.isDisabled}
>
Let Me In
</button>
const Example = () => {
const [value, setValue] = React.useState("");
function handleChange(e) {
setValue(e.target.value);
}
return (
<input ref="email" value={value} onChange={handleChange}/>
<button disabled={!value}>Let me in</button>
);
}
export default Example;
<button disabled={false}>button WORKS</button>
<button disabled={true}>button DOES NOT work</button>
Now just use useState or any other condition to pass true/false into the button, assuming you are using React.
its simple let us assume you have made an state full class by extending Component which contains following
class DisableButton extends Components
{
constructor()
{
super();
// now set the initial state of button enable and disable to be false
this.state = {isEnable: false }
}
// this function checks the length and make button to be enable by updating the state
handleButtonEnable(event)
{
const value = this.target.value;
if(value.length > 0 )
{
// set the state of isEnable to be true to make the button to be enable
this.setState({isEnable : true})
}
}
// in render you having button and input
render()
{
return (
<div>
<input
placeholder={"ANY_PLACEHOLDER"}
onChange={this.handleChangePassword}
/>
<button
onClick ={this.someFunction}
disabled = {this.state.isEnable}
/>
<div/>
)
}
}