How do I make react input show state value-ReactJS - reactjs

By using class, here is a small ref for all of you :
Class ShowValue Extends Component{
constructor(props){
super(props);
this.state = {
name: “ “,
}
}
onChangeHandler = (e) => {
this.setState(
name: e.target.value,
)
}
render(){
return (
<input type=” text” onChange={this.onChangeHandler} value=” My name”>
<p>{this.state.name}</p>
);
}
}
Am I able to create a variable for each input field, and listening on the onChange event and then call the “set” function for that variable by using hooks.

I have changed your code, now if you write in the input text it will be saved in your state name or vice-versa if you write in your code something in state name it will appear in the input.
I recommend you to check some tutorials or even the official doc
import React from 'react';
class ShowValue extends React.Component {
constructor(props) {
super(props);
this.state = {
name: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ name: event.target.value });
}
render() {
return (
<div>
<input
value={this.state.name}
type="text"
onChange={this.handleChange}
/>
<p>{this.state.name}</p>
</div>
);
}
}
export default ShowValue;
Have in mind:
You need to write a parent element to return different child elements otherwise it will give you error. So i've wrapped the input and p element.
You can not use ” for strings in javascript single quotes or double quotes
' or "
Demo: https://stackblitz.com/edit/react-j4a4dv?file=src%2FShowValue.js

Show the value inside the input by setting the value property of input
<input value={this.state.name} type=”text” onChange={this.onChangeHandler} >

Related

Moving props data to state to generate forms

I'm planning to add a prefilled form with React. I have the actual data on props. This is what I came up with.
#connect(...)
class Some extends React.Component {
state = {
...this.props.auth.user
}
render() {
// Create a form using the data on state
}
}
It looks not correct since I'm not using a react lifecycle hook here. I would like to ask if there is a better practice to achieve what I'm trying to do.
I am not sure about your architecture,since you are using uncontrolled component here, it is recommended to keep the source of truth at one place.
you can do something like this:
#connect(...)
class Some extends React.Component {
constructor(props) {
super(props);
this.state = {
userName:this.props.auth.user
}
}
handleChange = (event) => {
this.setState({userName: event.target.value});
}
render() {
return(
<div>
<input onChange={this.handleChange} id="some" type="text" value= {this.state.userName}/>
</div>
)
}
}
If you want to use controlled component that is controlled through parent/container. you can manage the values through props and set the props onChange.
So to elaborate on my previous responses you would do something like this to achieve what you want:
#connect(...)
class Some extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
}
}
handleChange = (event) => {
this.setState({ value: event.target.value });
}
render() {
return(
<div>
<input onChange={this.handleChange} id="some" type="text" value= {this.state.value|| this.props.value}/>
</div>
)
}
}
While your value is an empty string (in the state), the fields will be populated from your props and as soon as you start typing it will overwrite the prepopulated values with the ones in your state.
Best practices would be to actually have a Component that handles this logic and then passes the props to the form that should be just a dumb presentational component:
class SomeController extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
}
}
handleChange = (event) => {
this.setState({ value: event.target.value });
}
return (<Form handleChange={this.handleChange} value={this.state.value} />)
}
And then your form component:
const Form = (props) => (
<form>
<input onChange={props.handleChange} value={props.value} />
</form>
);
Hope this explanation helps.

how to fix "Cannot read property 'options' of null" in this code?

I want to add the user to the options array which I have defined inside the state. Problem is whenever I use prevstate.options.concat([username]). it shows this error. While when I just push username using this.state.push(username) to the array no error occurs. But for good practice in React we never alter directly the state variable, that's why I was using prevstate so I want to know why I am getting this error.
As I am getting value of user and this.state.options also showing in the console when I declare inside adduserso I want to know why my setState is not working using prevstate variable?
class Login extends React.Component{
constructor(props){
super(props);
this.addUser = this.addUser.bind(this)
this.State = {
options : ['hello']
}
}
addUser(username){
console.log(username)
console.log(this.State.options)
this.State.options.push(username)
this.setState((prevState)=>{
// console.log(prevState.options)
return {
options : prevState.options.concat([username])
}
})
}
render(){
return(
<div>
<Form addUser = {this.addUser}/>
</div>
);
}
}
class Form extends React.Component{
constructor(props){
super(props);
this.formData = this.formData.bind(this);
}
formData(e){
e.preventDefault();
const username = e.target.elements.user.value.trim();
console.log(username);
this.props.addUser(username);
}
render(){
return(
<div>
<form onSubmit={this.formData}>
Name: <input type="text" name="user"></input>
<input type ="submit"></input>
</form>
</div>
)
}
}
ReactDOM.render(<Login /> , document.getElementById('app'));
actual result would be to concat a user in the options array using setState
Okay I have mocked your component in a sandBox and the following seems to be working. Here is the sandBox: https://codesandbox.io/s/mq3qyvvjkx
You're issue seems to have been using this.State instead of this.state (lower case s) multiple times in your component. And this looks why you were receiving your error.
class Login extends React.Component {
constructor(props) {
super(props);
this.addUser = this.addUser.bind(this);
this.state = {
options: ["hello"]
};
}
addUser(username) {
console.log(username);
console.log(this.state.options);
this.state.options.push(username);
this.setState(prevState => {
// console.log(prevState.options)
return {
options: prevState.options.concat([username])
};
});
}
render() {
return (
<div>
<Form addUser={this.addUser} />
</div>
);
}
}
class Form extends React.Component {
constructor(props) {
super(props);
this.formData = this.formData.bind(this);
}
formData(e) {
e.preventDefault();
const username = e.target.elements.user.value.trim();
console.log(username);
this.props.addUser(username);
}
render() {
return (
<div>
<form onSubmit={this.formData}>
Name: <input type="text" name="user" />
<input type="submit" />
</form>
</div>
);
}
}
The following produces the following console outputs, with no console errors.
Corbuk
Corbuk
["hello", "corbuk"]
Please let me know if this is the expected output?

React - Passing State to child component

My Parent Class which holds the overall App state
class App extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: 1,
};
this.handleChange = this.handleChange.bind(this);
};
handleChange(event) {
const target = event.target;
const newValue = target.value;
if( Math.sign(newValue) === 1 ) {
this.setState({
inputValue: newValue
});
}
}
render() {
return (
<EngInput type="number" value={this.state.inputValue} onChange={this.handleChange}/>
);
}
}
My child component to which I am passing the state as props.
class EngInput extends React.Component {
render() {
return (
<input
type="number"
defaultValue={this.props.value}
onChange={this.props.onChange}
/>
);
}
}
The logic I am trying to implement being - The child input component should accept only positive numbers. If its a negative number, the state should not change and the UI should update to the inputValue instead of the newValue.
But, whats happening in the above code is, even though the state does not change to non negative value, the UI still accepts negative value.
How to implement a logic like, if the value is negative, the UI should still show the old positive value from state.
Use value instead of defaultValue to control the input from the parent component.
class EngInput extends React.Component {
render() {
return (
<input
type="number"
value={this.props.value}
onChange={this.props.onChange}
/>
);
}
}

React child receive old state props, NOT updated state props

I have a funky set up. I need a multi stage registration form. I have a parent:
class ContactPage extends React.Component {
constructor(props){
super(props);
this.state = {
stage:0,
name:'',
message:'',
email:'',
phone:''
}
this.setName=(e)=>{
this.setState({name:e});
}
this.setMessage=(e)=>{
this.setState({message:e});
}
this.setEmail=(e)=>{
this.setState({email:e});
}
this.setPhone=(e)=>{
this.setState({phone:e});
}
this.nextStage=()=>{
if(this.state.stage < 3){
this.setState({stage:this.state.stage+1})
}
}
this.previousStage=()=>{
if(this.state.stage >= 1){
this.setState({stage:this.state.stage-1})
}
}
this.stage = [
<ContactName onChange={this.setName} />,
<ContactInfo />,
<ContactMessage name={this.state.name} onChange={this.setMessage} />,
<Send />
]
}
render(){
return (
<div>
{this.stage[this.state.stage]}
<button primary style={style.button} onClick={this.previousStage}> Previous </button>
<button primary style={style.button} onClick={this.nextStage}> Next </button>
</div>
This component renders children based on in what stage of registration the user is. I can receive callbacks from children in parent(children do set the state of the parent), but, when passing state.name from parent to child as a prop, the child receives the initial state, which means the name is empty string.
Child component:
class ContactMessage extends React.Component {
constructor(props){
super(props);
this.state ={
message:'',
name:''
}
this.handleChange=(event)=>{
this.props.onChange(event.target.value);
this.setState({message: event.target.value});
}
}
componentWillReceiveProps(props){
this.setState({name:props.name})
}
render(){
return(
<div>
<h1>{this.state.name}</h1>
<form onSubmit={this.handleSubmit}>
<label htmlFor='messageField'>
Message:
<input className='messageField' type="textfield" value={this.state.message}
onChange={this.handleChange} />
</label>
</form>
</div>
UPDATE: I am receiving initial props in the child components, not updated props from parent state. How do I receive new and updated props from parent state?
As I see, in ContactPage you trying to set event (e) as value of state.name instead of setting this.setState({ name: e.target.value }) in this. setName method.
By the way, you don't have to pass everything through constructor.
For example,
class MyComponent extends Component {
state = {
name: ''
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
render() {
return (
<input name="name" value={this.state.name} onChange={this.handleChange} />
);
}
}
Try extracting the stage array into its own method. Something like:
class ContactPage extends Component {
constructor(props) {
this.state = {
stage: 0,
name: 0
// and so on
}
}
getStage(index) {
let stages = [
<ContactName onChange={this.setName} />,
<ContactInfo />,
<ContactMessage name={this.state.name} onChange={this.setMessage} />,
<Send />
];
return stages[index];
}
render() {
return (
{this.getStage(this.state.stage)}
<AllTheOtherStuff />
)
}
}
3 things I'm noticing here, which may or may not be your problem.
First: Using state the way you are is inherently bug prone. If you are displaying this.state.name, and are setting name from this.props, both in the constructor and componentWillReceiveProps, then just skip the middle man and display this.props.name instead. Trying to maintain a correct state when the value in state is coming from props is really easy to mess up, thus it is better to just use props directly.
Second: I believe your problem is a mixture of 1 and 2 here, but you are declaring your stage variable in your constructor, so it is only going to use what it has available in the constructor. Move this.stage into your render() and it should display the correct state information.
Third: the way you are using componentWillReceiveProps can lead to confusion. It is better to name your variables something that accurately describes what they are, without possible confusion. I would change componentWillReceiveProps(props) to componentWillReceiveProps(nextProps) since nextProps is more explicit about what those props are you are dealing with.

How come I can't type anything into my React search box?

I have a component called SearchInput and it has in it
<input
type='text'
className='input-field'
value={value}
placeholder={this.state.placeholder}
// onFocus={::this.onFocus}
// onBlur={::this.onBlur}
// onKeyUp={::this.onKeyUp}
// onKeyDown={::this.hanleArrowKeys}
// onChange={::this.onChange}
/>
However, when I type anything into it, nothing happens. The text doesn't even appear. What am I doing wrong?
Probably your state is not updating, maybe didn't you bind "this" to function onChange?
Here is an example of correct input in react:
class SearchInput extends Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.setState({ value: event.target.value });
}
render() {
return <input type="text" value={this.state.value} onChange={this.handleInputChange}/>;
}
}
Probably you are binding the value of the input box with an attribute in the state of the component and you are either not providing an onChange prop to the input tag or your onChange callback method is not updating the attribute in the state to which the input tag's value is bound.

Resources