how to create a simple class-based react input component? - reactjs

I am trying to create a text input component that has an initial value. The problem is that I can either have an initial value or I can change its value.
Im very beginner so please dont be rude.
This is my code:
import * as React from "react";
export class TextBox extends React.Component<{ value: any, onBlur?: Function, isAutoFocus?: boolean }> {
constructor(props) {
super(props);
this.state = {
value: props.value
}
/*this.setState({
value: props.value
})*/
}
public render() {
return <input /*value={this.props.value}*/ autoFocus onChange={(event) => { console.log("set new value"); this.setState({ value: event.target.value }) }} ></input>;
}
}

You just need to use the state instead of props to control the input's value
export class TextBox extends React.Component<{ value: any, onBlur?: Function, isAutoFocus?: boolean }> {
constructor(props) {
super(props);
this.state = {
value: props.value // this sets the initial value to what is passed from the props
}
}
public render() {
return <input value={this.state.value} autoFocus onChange={(event) => {this.setState({ value: event.target.value })}} ></input>;
}
}

class TextInput 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) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} /> </label>
<input type="submit" value="Submit" />
</form>
);
}
}

Related

ReactJs input first value getting empty

import React, { Component } from "react";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { value: "" };
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
console.log(this.state.value);
this.setState({ value: event.target.value });
}
render() {
return (
<form>
<label>
Name:
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
console log screenshot
I'm getting first input value empty. I have different app. I'm basically try to doing tip calculator app. I don't need submit button. The user will enter a value, but it does not calculate correctly because the first value is empty. At the same time, it does not show the last value entered, only when clicked, all the entered values are correct. By the way, i got this form from React own site, but it's the same error that i encountered. Thank you!
Your console.log logs the value before you change it. Thus it will always be the previous value.
You also have to keep in mind that the Component.setState method might not execute immediately.
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.
Therefore you should use a callback. E.g.
handleChange(event) {
this.setState({ value: event.target.value }, () => {
console.log(this.state.value);
});
}
Here is an executable example. Click Run code snippet.
class App extends React.Component {
constructor(props) {
super(props);
this.state = { value: "" };
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value }, () => {
console.log(this.state.value);
});
}
render() {
return (
<form>
<label>
Name:
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Set initial value to 0 so that it will not be empty.
this.state = { value: 0 };
Also move your console.log as callback function to setState so that you can see the updated value.
import React, { Component } from "react";
export default class App2 extends React.Component {
constructor(props) {
super(props);
this.state = { value: 0 };
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value }, () => {
console.log(this.state.value);
});
}
render() {
return (
<form>
<label>
Name:
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

How to clear the inputs in function using React bootstrap typeahead

I am trying the clear the inputs in the function using following code.
import {Typeahead} from 'react-bootstrap-typeahead';
type requestState={
value:string[]
}
class Data extends Component<{},requestState> {
constructor(props){
super(props);
this.state = {
value: [],
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.typeahead.getInstance().clear();
}
render() {
return(
<Typeahead
ref={(ref) => this.typeahead = ref}
id="data"
labelKey="data"
multiple={true}
options={this.state.values}
placeholder="Choose a data.."
onChange={(e) => this.handleChange(e)}
/>
);
}
}
export default Data;
When I try using this code to clear the inputs at once, I am getting following error: "Property 'typeahead' does not exist on type 'Data'".
Could someone help me how to define typeahead property and what changes have to do to get this working.
This is a react ref issue and you just need to define the ref for use first.
Using classical definition:
class Data extends Component<{},requestState> {
constructor(props){
super(props);
this.state = {
value: [],
}
this.handleChange = this.handleChange.bind(this);
this.typeahead = null;
}
handleChange(e) {
this.typeahead.getInstance().clear();
}
render() {
return(
<Typeahead
ref={(ref) => this.typeahead = ref}
id="data"
labelKey="data"
multiple={true}
options={this.state.values}
placeholder="Choose a data.."
onChange={(e) => this.handleChange(e)}
/>
);
}
}
Using React.createRef
class Data extends Component<{},requestState> {
constructor(props){
super(props);
this.state = {
value: [],
}
this.handleChange = this.handleChange.bind(this);
this.typeahead = createRef<Typeahead>();
}
handleChange(e) {
this.typeahead.current.getInstance().clear();
}
render() {
return(
<Typeahead
ref={this.typeahead}
id="data"
labelKey="data"
multiple={true}
options={this.state.values}
placeholder="Choose a data.."
onChange={(e) => this.handleChange(e)}
/>
);
}
}
Refs and the DOM
This Changes worked for me in typescript to clear the inputs using React Bootstrap Typeahead
import React, { Component } from 'react';
import {Typeahead} from 'react-bootstrap-typeahead';
class Data extends Component<{},requestState> {
typeahead = React.createRef<Typeahead>();
constructor(props){
super(props);
this.state = {
value: [],
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.typeahead.current.state.selected= []
}
render() {
return(
<Typeahead
ref={this.typeahead}
id="data"
labelKey="data"
multiple={true}
options={this.state.values}
placeholder="Choose a data.."
onChange={(e) => this.handleChange(e)}
/>
);
}
}
export default Data;

Why value of input here at reactjs is undefined?

I want to change state by the value of input but it is undefined.
It should work, the value is for every HTML tag so what is wrong with my code??
import React, { Component } from "react";
class App extends Component {
constructor() {
super();
this.state = {
firstName: " "
};
this.handleChange = this.handleChange(this);
}
handleChange(event) {
this.setState({
firstName: event.target.value
});
}
render() {
return (
<form>
<input
type="text"
placeholder="Firstname"
onChange={this.handleChange}
/>
<h1>{this.state.value}</h1>
</form>
);
}
}
export default App;
There's no value stored in your state, so it is undefined, and you do not correctly bind this to your handler. Output this.state.firstName instead:
import React, { Component } from "react";
class App extends Component {
constructor() {
super();
this.state = {
firstName: " "
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
firstName: event.target.value
});
}
render() {
return (
<form>
<input
type="text"
placeholder="Firstname"
onChange={this.handleChange}
/>
<h1>{this.state.firstName}</h1>
</form>
);
}
}
export default App;
First try to bind this for handleChange using an arrow function. Also use the state variable to set the value property of the input .
Sandbox link: https://codesandbox.io/s/react-basic-example-qmyw5
import React, { Component } from "react";
class App extends Component {
constructor() {
super();
this.state = {
firstName: " "
};
}
handleChange = (event) => {
this.setState({
firstName: event.target.value
});
}
render() {
return (
<form>
<input
type="text"
placeholder="Firstname"
onChange={this.handleChange}
value={this.state.firstName}
/>
<h1>{this.state.firstName}</h1>
</form>
);
}
}
export default App;

React component: Simulate standard HTML <input/> API

I want to make a component with an API like any standard input element, meaning I want to use it like this: <CustomInput value={this.state.custom_input_state} onChange={this.handleChange} />
Here is what I have so far, but I have no idea how to
Make the custom components value changeable from the parent component
after it has been constructed
Make the parent's onChange handler function recieve a change event when the
custom component's value changes
Here is my test setup:
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
foo: 0
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.increment = this.increment.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
alert(this.state.foo);
event.preventDefault();
}
increment() {
this.setState({foo: this.state.foo + 1});
}
render() {
return(
<form onSubmit={this.handleSubmit}>
<div onClick={this.increment}>Increment from parent</div>
<CustomInput name="foo" value={this.state.foo} onChange={this.handleChange}/>
<input type="submit" value="Submit" />
</form>
)
}
}
class CustomInput extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value,
};
this.increment = this.increment.bind(this);
}
increment() {
this.setState({value: this.state.value + 1});
}
render() {
return(
<React.Fragment>
<div onClick={this.increment}>Increment self</div>
<input name={this.props.name} value={this.state.value}/>
</React.Fragment>
);
}
}
You have to pass all the CustomInput props to the input element. In CustomInput component actually it not recieving the onChange event.
Pass the prop onChange event to input element
Form Component
class Form extends Component {
constructor() {
super();
this.state = {
foo: 'React'
};
}
handleChange = (event) => {
this.setState({
[event.target.name]:event.target.value
})
}
render() {
return (
<div>
<form>
<Custominput name="foo" onChange={this.handleChange} value={this.state.foo} />
</form>
{this.state.foo}
</div>
);
}
}
CustomInput Component
export default class CustomInput extends React.Component{
render(){
return(
<input {...this.props} />
)
}
}
demo link

React updating state within the same component

I am new to react, I thought setting state will re-render react component. Did I miss something here, my text is not displayed until I call this.forceUpdate().
export default class Hello extends React.Component {
constructor(props){
super(props);
this.state = { value: ''};
this.handleChange = this.handleChange.bind(this);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
<p> You entered {this.state.value} </p>
</div>
);
}
handleChange(event){
this.state = { value: event.target.value };
this.forceUpdate();
}
}
You should call .setState method instead of assign new value to this.state
handleChange(event){
this.setState({ value: event.target.value })
}

Resources