Why my onInput doesn't work to change props.name? - reactjs

I am learning React.js and I want to use onInput event to change the name, but it doesn't work.
Why is this happening? Do I write the wrong function(OnInputChange)?
Here is my app.js
import React, { Component } from "react";
import UserInput from "./Components/UserInput";
import UserOutput from "./Components/UserOutput";
class App extends Component {
state = {
Username: [{ name: "Jacky" }]
};
OnInputChange = event => {
this.setState({
Username: [{ name: "event.target.value" }]
});
};
render() {
return (
<div>
<UserInput OnInput={this.OnInputChange} />
<UserOutput name={this.state.Username[0].name} />
</div>
);
}
}
export default App;
my UserInput.js:
import React from "react";
const UserInput = () => {
return (
<div>
<input type="text" />
</div>
);
};
export default UserInput;
my UserOutput.js:
import React from "react";
const UserOutput = props => {
return (
<div>
<p>I am {props.name}</p>
<p>I am {props.name}</p>
</div>
);
};
export default UserOutput;

Changes:
1- You are not assigning onChange handler to input element in UserInput component, only passing that handler in props, automatically it will not work.
2- You are updating the value in state in wrong way, it should be name: event.target.value (not string).
Code:
const UserInput = (props) => {
return(
<div>
<input type="text" onChange={props.OnInput}></input>
</div>
);
}
OnInputChange = (event) => {
this.setState({
Username:[
{ name: event.target.value },
],
});
}
Working Code:
class App extends React.Component {
state = {
Username: [{ name: "Jacky" }]
};
OnInputChange = event => {
this.setState({
Username: [{ name: event.target.value }]
});
};
render() {
return (
<div>
<UserInput OnInput={this.OnInputChange} />
<UserOutput name={this.state.Username[0].name} />
</div>
);
}
}
const UserInput = (props) => {
return (
<div>
<input type="text" onChange={props.OnInput} />
</div>
);
};
const UserOutput = props => {
return (
<div>
<p>I am {props.name}</p>
<p>I am {props.name}</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('app'))
<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='app' />

Your OnInput property is not passed down to your input component. It would have to be:
const UserInput = props => {
return(
<div>
<input type="text" onChange={props.OnInput} />
</div>
);
};
Your handler uses a literal string 'event.target.value', it must read the value:
Username: [{ name: event.target.value }],
Also, there is no need to wrap username in an array and another object, you can just use:
Username: event.target.value,
and access this.state.Username.
and initialize as
state = {
Username: "Jacky"
};

1.) You need to pass the event handler to your UserInput component.
const UserInput = ({ onChange }) => {...}
and then
<UserInput onChange={this.OnInputChange} />
2.) You need to use the passed event handler in your input onChange.
<input onChange={onChange} />
3.) You need to use event.target.value not 'event.target.value'.

Related

How can I take a input from user and change it with setState?

constructor() {
super();
this.state = {
name: "",
name1: "",
};
}
change = () => {
this.setState({ name: this.state.name1 });
};
handleChange = (e) => {
this.setState({ name1: e.target.value });
};
render() {
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={this.handleChange}
></input>
<button onClick={this.change}>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
);
}
This is what I did but feels like it is nonsense on actual webpage even it works. Is there a better way to take input from user?
Why you need name and name1 in state. Just name should be fine. See the below code if that helps
I am not sure why you handle a event in button. May you can use a form with OnSubmit.
import React from "react";
import "./style.css";
export default class App extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
}
render() {
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={(e) => this.setState({name: e.target.value})}
/>
<button>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
);
}
}
Your onChange in the input would be
onChange={event => this.handleChange(event)}
And for the button it would be
onChange{() => this.change()}
We would not require 2 states for the name but we would need one variable to store the name and second variable to let the component know that name has been update. We need the second variable because on button click only the name has to be updated(as per the code mentioned).The component would re-render when a state is updated. Below code might be helpful.
class Content extends React.Component {
constructor(){
super()
this.state = {
name: "",
}
this.name=''
}
change = () => {
this.setState({name: this.name})
}
handleChange = (e) => {
this.name=e.target.value
}
render(){
return(
<div>
<input type = "text" placeholder="Enter your name" onChange={this.handleChange}></input>
<button onClick={this.change}>Click Me!</button>
<h4>Hello! {this.state.name}</h4>
</div>
)
}}
Here is a version with React Hooks:
import React, { useState } from 'react';
export default function App() {
const [name, setName] = useState('');
const handleNameChange = (e) => {
const nameInput = e.target.value;
setName(nameInput);
};
return (
<div>
<input
type="text"
placeholder="Enter your name"
onChange={(e) => handleNameChange(e)}
></input>
<button>Click Me!</button>
<h4>Hello! {name}</h4>
</div>
);
}

react-router - how change the url

I need to have the user edit the url the "path" appears in the input of the other component and when searching the input change the url in real time. How can I use "withRouter" to perform this function?
// App.js component
class App extends Component {
render() {
const { match, location, history } = this.props;
return (
<div >
<Search
searchString={location.pathname}
/>
</div>
)
}
}
export default withRouter(App)
//Search.js component
const Search = ({ searchString }) => (
<div>
<input
value={searchString}
type="search"
placeholder="Search"
aria-label="Search"
/>
</div>
)
This should work for you although I'm not sure redirecting user to another page while typing into search input is a good UX.
// App.js component
class App extends Component {
state = {
searchString: this.props.location.pathname
}
handleSearch = (event) => {
this.setState(
{ searchString: event.target.value },
() => this.props.history.push('/search?query=' + this.state.searchString)
);
}
render() {
return (
<div >
<Search
onChange={this.handleSearch}
searchString={this.state.searchString}
/>
</div>
)
}
}
export default withRouter(App)
const Search = ({ searchString, onChange }) => (
<div>
<input
onChange={onChange}
value={searchString}
type="search"
placeholder="Search"
aria-label="Search"
/>
</div>
)

React input cursor position moves to the end?

I came across with this scenario where I want to "sanitize" the input before calling onChange, however even without re-render, the cursor moves to the end. why?
class Input extends React.Component {
state = { value: this.props.value };
onChange = e => {
let nextValue = e.target.value;
if (!/[0-9]/.test(nextValue)) {
this.setState({ value: nextValue });
}
};
render() {
console.log("render");
return (
<input type="text" value={this.state.value} onChange={this.onChange} />
);
}
}
ReactDOM.render(<Input value="type something here" />, 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"/>
You can use onKeyPress to sanitize an input before onChange, without "side effects".
Code Sandbox: https://codesandbox.io/s/9jlm59n52r
import React from "react";
import ReactDOM from "react-dom";
class Input extends React.Component {
state = { value: this.props.value };
handleKeyPress = e => {
let keyPressed = e.key;
if (/[0-9]/.test(keyPressed)) {
e.preventDefault();
}
};
handleChange = e => {
this.setState({ value: e.target.value });
};
render() {
return (
<input
type="text"
value={this.state.value}
onKeyPress={this.handleKeyPress}
onChange={this.handleChange}
/>
);
}
}
ReactDOM.render(
<Input value="type something here" />,
document.getElementById("root")
);
EDIT:
Sanitize input on paste:
handlePaste = e => {
let pastedText = e.clipboardData.getData("text/plain");
if (/[0-9]/.test(pastedText)) {
e.preventDefault();
}
}
...
<input
...
onPaste={this.handlePaste}
...
/>

clear the material UI text field Value in react

How to clear the materialUI textfield value in react?
Check the below code -
<TextField
hintText=""
ref={(node) => this._toField = node}
onChange={this.changeToText}
floatingLabelText="To*"
floatingLabelFixed={true}
fullWidth={true}
/>
I'm using the raisedButton while pressing it validate the above field. If the field has error then displaying the error message. If not, then we need to clear the input. But how can we clear the input text?
if you are using a stateless functional component then you can use react hooks.
Also make sure you are using inputRef
import React, { useState, useRef } from "react";
let MyFunctional = props => {
let textInput = useRef(null);
return (
<div>
<Button
onClick={() => {
setTimeout(() => {
textInput.current.value = "";
}, 100);
}}
>
Focus TextField
</Button>
<TextField
fullWidth
required
inputRef={textInput}
name="firstName"
type="text"
placeholder="Enter Your First Name"
label="First Name"
/>
</div>
);
};
There is a value property that you have to pass to the TextField component.
check example below:
class SomeComponent extends Component {
state = {value: ''}
resetValue = () => {
this.setState({value: ''});
}
render() {
return (
<div>
<TextField
...
value={this.state.value}
/>
<button onClick={this.resetValue}>Reset</button>
</div>
)
}
}
try this
import { Button, Container, InputBase } from '#material-ui/core'
import React, { useState } from 'react'
const ClearText = ()=> {
const [text , setText] = useState("")
const clearTextField = () => setText("")
return (
<Container>
<InputBase
value={text ? text : ""}
onChange={(e)=>setText(e.target.value)}
/>
<Button onClick={clearTextField} > Clear </Button>
</Container>
)
};
export default ClearText;
You need to, somehow, store the input's value. State seems to be an initial approach in this case. Whenever the text changes, you have to update the state. Same applies when you click the button and click the input's value afterwards:
class App extends React.Component {
constructor() {
super()
this.state = {
value: ''
}
this.handleChange = this.handleChange.bind(this)
this.handleClick = this.handleClick.bind(this)
}
handleChange(event) {
this.setState({ value: event.target.value })
}
handleClick() {
// validation...
this.setState({ value: '' })
}
render() {
return (
<div>
<input type="text" value={this.state.value} onChange={this.handleChange}/>
<button onClick={this.handleClick}>Click-me</button>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<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>
<div id="root"></div>

React Component Not Updating After Changing A Value

In ReactJS, I'm writing a stateless component;
Since I've read avoiding unnecessary states is best practice.
The component represents an input field which executed a function when the input box contains a value.
export const InputField = (props) => {
const InputFieldContentsChanged = (event) => {
props.onChange(event.target.value);
};
return (
<div data-component="input-field"
className={(props.value !== "" ? "value": "")}>
<input type={props.type} value={props.value} onChange={InputFieldContentsChanged} />
<span className="bar"></span>
<label>{props.label}</label>
</div>
);
};
InputField.PropTypes = {
type: PropTypes.oneOf([ "text", "password" ]).isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.string,
onChange: PropTypes.func.isRequired
}
Now,
I've created another component which just is a sample to test the component above.
This looks like the following:
export const SampleComponent = (props) => {
let componentUsername = "";
const onUsernameChanged = (username) => {
componentUsername = username;
};
return (
<InputField type="text" label="Username" value={componentUsername} onChange={onUsernameChanged} />
);
};
So, I'm binding the value to a custom variable in the component which is changed when the contents of the input field does change.
How does it come that the input field component does not update itself with the new username?
Kind regards,
I'm writing a stateless React component since it's best practice to avoid state when not needed.
In your code you are trying to use your own kind of "state" though, and it's just a variable (componentUsername). But since it's not React state, the component does not re-render upon the change of the variable. React simply doesn't know about the change.
So, either use the usual setState instead of re-assigning the your own "state" variable, or put the logic in the parent component and pass the componentUsername to the SampleComponent via props:
const SampleComponent = props => (
<input type="text" onChange={props.onChange} value={props.value} />
);
class ParentComponent extends React.Component {
constructor() {
super();
this.state = { value: '' };
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
console.log(e.target.value);
this.setState({ value: e.target.value });
}
render() {
return (
<SampleComponent
value={this.state.value}
onChange={this.handleInputChange}
/>
);
}
}
ReactDOM.render(<ParentComponent />, document.getElementById('root'));
<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>
<div id="root"></div>
The idea of functional components is to not perform any changes to the state or props.
Since there is no trigger to re-render you component you won't see any change.
Change this React.Function to a React.Component.
const InputField = (props) => {
const InputFieldContentsChanged = (event) => {
console.log(event.target.value);
props.onChange(event.target.value);
};
return (
<div data-component="input-field"
className={(props.value !== "" ? "value": "")}>
<input type={props.type} value={props.value} onChange={InputFieldContentsChanged} />
<span className="bar"></span>
<label>{props.label}</label>
</div>
);
};
class SampleComponent extends React.Component {
constructor() {
super();
this.state = { componentUsername : ""};
}
onUsernameChanged = (username) => {
console.log(username);
this.setState({componentUsername: username});
}
render() {
return (
<InputField type="text" label="Username" value={this.state.componentUsername} onChange={this.onUsernameChanged} />
);
}
};
ReactDOM.render(<SampleComponent/>, document.getElementById('app'));
<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>
<div id="app"></div>

Resources