Currently very new to React. Trying to make a input box and when I type into the input box and click submit, an alert box pops up with the text that I typed.
import React from "react";
import "./App.css";
class TodoListt extends React.Component {
state = {};
constructor(props) {
super(props);
this.input = React.createRef();
}
handleSubmit(e) {
e.preventDefault();
console.log(this._inputElement.value);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input ref={a => (this._inputElement = a)} placeholder="...todo" />
<button>submit</button>
</form>
</div>
);
}
}
export default TodoListt;
TypeError: Cannot read property '_inputElement' of undefined
Change handleSubmit to an arrow function:
handleSubmit = (e) => {
e.preventDefault();
console.log(this._inputElement.value);
}
This is an excellent article on the subject.
Try this:
import React from "react";
import "./App.css";
class TodoListt extends React.Component {
state = {};
constructor(props) {
super(props);
this.input = React.createRef();
}
handleSubmit(e) {
e.preventDefault();
console.log(this.input.current.value);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input ref={this.input} placeholder="...todo" />
<button>submit</button>
</form>
</div>
);
}
}
export default TodoListt;
Related
I want to get the value of TextField input and render the message conditionally. I tried this one, its working but this one is functioning dynamically because I used onChange. I want to achieve the same but using onSubmit on <Button> Is there anyway to do that?
import React from 'react';
import { Component } from 'react';
import Button from '#mui/material/Button';
import { TextField } from '#mui/material';
class App extends Component
{
state = {
myValue: null,
}
handleChange = (e) => this.setState({
myValue: e.target.value
})
render() {
return (
<div>
<TextField
value={this.state.myValue}
onSubmit={this.handleChange}
/>
<button >Get Weather</button>
{this.state.myValue ? <p>value inputed </p>: <p>no input</p>}
</div>
)
}
}
export default App;
Using Refs is what you need. You can get the current value of your input by clicking a button and only then change the state.
Demo
import React, { createRef } from "react";
import { Component } from "react";
import { TextField } from "#mui/material";
class App extends Component {
constructor(props) {
super(props);
this.textInput = createRef();
this.state = {
myValue: ""
};
}
showRefContent = () => {
this.setState({
myValue: this.textInput.current.value
});
};
handleChange = (e) =>
this.setState({
myValue: e.target.value
});
render() {
return (
<div>
<TextField inputRef={this.textInput} />
<button onClick={this.showRefContent}>Get Weather</button>
<p>
{this.state.myValue.length > 0
? `text:${this.state.myValue}`
: "no text"}
</p>
</div>
);
}
}
export default App;
you just need to you onkeydown instead onsubmit.
<TextField
value={this.state.myValue}
onKeyDown={this.handleChange}
/>
or use
<form onSubmit={handleChange }>
<TextField
value={this.state.myValue}
onKeyDown={this.handleChange}
/>
<button type="submit">submit</button>
</form>
I'm new to React and I'm stuck in this problem. I have a toggle component that is rendering a button to show/hide data aswell as the data that is being rendered.
I want to separate both the button and the data so I can display the content in another component, and being able to hide it and show it from the toggle component, if it makes sense.
Here is a picture to demonstrate what I'm wishing to do.
Toggle Example
The toggleComponent.js that contains the button and the data :
import React, { Component } from 'react';
export default class toggleComponent extends React.Component{
constructor(){
super();
this.state={
isShowBody: false
}
}
handleClick = (event) => {
this.setState({ isShowBody: !this.state.isShowBody })
}
checkbox = () => {
return (
<div >
<span className="switch switch-sm" >
<label>
<input type="checkbox" name="select" onClick={this.handleClick.bind(this)}/>
<span />
</label>
</span>
</div>
)
}
content = () => {
return (
<div>
Displaying text
</div>
)
}
render() {
return (
<div>
{this.checkbox()}
{this.state.isShowBody && this.content ()}
</div>
);
}
}
Just make another component named content.js. Import ContentComponent inside ToggleComponent and render it using flag.
Stackblitz Demo
Solution:
Toggle Component
import React, { Component } from "react";
import ContentComponent from "./content.js";
export default class toggleComponent extends React.Component {
constructor() {
super();
this.state = {
isShowBody: false
};
}
handleClick = event => {
this.setState({ isShowBody: !this.state.isShowBody });
};
checkbox = () => {
return (
<div>
<span className="switch switch-sm">
<label>
<input
type="checkbox"
name="select"
onClick={this.handleClick.bind(this)}
/>
<span />
</label>
</span>
</div>
);
};
render() {
return (
<div>
{this.checkbox()}
{this.state.isShowBody && <ContentComponent />}
</div>
);
}
}
Content Component
import React, { Component } from "react";
export default class ContentComponent extends React.Component {
content = () => {
return <div>Displaying text</div>;
};
render() {
return <div>{this.content()}</div>;
}
}
I've created a component which displays only block[0] value, it is not showing the whole block value.
For Example, if I write :
HI
Stackoverflow
It is showing only "Hi", It's not showing the full content of the field.
Can anyone help me in getting the whole data whatever I write in that input field?
import React from "react";
import { Editor } from "react-draft-wysiwyg";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
export default class Edit extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<Editor value={this.props.value} onChange={this.props.onChange} />
</div>
);
}
}
App component:
import React from "react";
import Body from "./Body";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
body: ""
};
}
changeBodyHandler = value => {
console.log(value.blocks[0].text);
this.setState({
body: value.blocks[0].text
});
};
render() {
return (
<div>
<Body
label="Body"
name="body"
value={this.state.body}
onChange={this.changeBodyHandler}
/>
</div>
);
}
}
export default App;
Here is the whole code:
"https://codesandbox.io/s/compassionate-tereshkova-89fm2"
Can anyone please help me with this?
Each line to list, then map(), join() with \n would be fine
this.setState({ body: value.blocks.map(x => x.text).join("\n") });
import React from "react";
import Body from "./Body";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
body: ""
};
}
changeBodyHandler = value => {
this.setState({ body: value.blocks.map(x => x.text).join("\n") });
};
render() {
console.log(this.state.body);
return (
<div>
<Body
label="Body"
name="body"
value={this.state.body}
onChange={this.changeBodyHandler}
/>
</div>
);
}
}
export default App;
Try it online:
If you want with break line like as it is in editor, add <p> tag while concatination.
changeBodyHandler = value => {
let data =value.block;
let text = "";
data.map(index => {
text = text +"<p>" +index.text+"</p>";
});
this.setState({
body: text
});
};
And if you want to display the data in same way somewher use dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{__html: this.state.body}} />
I'm having trouble with this issue of context:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class Foo extends Component {
constructor(props) {
super(props)
this.state = {
error: false
}
}
render() {
const { handleChange } = this.props;
let _handleChange = handleChange.bind(this);
return (
<div>
<input type='file' onChange={_handleChange} id='input'/>
<label htmlFor='input'> Upload </label>
{this.state.error && <span>{this.state.errorMessage}</span>}
</div>
)
}
}
class FooClosure extends Component {
handleChange = (event) => {
let self = this // this will always be FooClosure
debugger // local this context will be Foo
this.setState({ error: true, errorMessage: 'Some error happened'})
}
render() {
return (
<div>
<Foo handleChange={this.handleChange} />
</div>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<FooClosure />
</div>
);
}
}
export default App;
I'm trying setState inside a function defined in a parent component that gets bound in the child component. My understanding of Javascript means that this would then be the child component, but this.setState is always executed in the context of FooClosure. Can anyone help me understand why this is?
I can fix this easily by defining handleChange = (event, self) => ... but I dont think I should have to do that.
This is how you should write it.
class Foo extends Component {
render() {
return (
<div>
<input type='file' onChange={this.props.handleChange} id='input'/>
<label htmlFor='input'> Upload </label>
{this.props.error && <span>{this.props.errorMessage}</span>}
</div>
)
}
}
class FooClosure extends Component {
constructor(props) {
super(props);
this.state = {error: false, errorMessage: ''};
}
handleChange = (event) => {
this.setState({ error: true, errorMessage: 'Some error happened'})
}
render() {
return (
<div>
<Foo handleChange={this.handleChange.bind(this)} error={this.state.error} errorMessage={this.state.errorMessage} />
</div>
)
}
}
When you're defining this in your handleChange method, you're explicitly telling the program to look at its current scope where the function is being written. Passing it as a prop will only run the function in its written scope, not redefine this, nor will redefining it in your Foo class prove helpful.
Imagine FooClosure and Foo are in two separate rooms and somehow became sentient beings. FooClosure has the ability to make pizzas. Foo has the ability to call FooClosure and ask for a pizza to be made. The problem here is Foo is asking FooClosure to make the pizza, but all the ingredients and the only working oven are in Foo's room.
The best thing to do in this situation is to move your handleChange method into your Foo class so this can reference Foo and not FooClosure which in turn allows you to set the state of Foo.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class Foo extends Component {
constructor(props) {
super(props)
this.state = {
error: false
}
}
handleChange = event => {
this.setState({
error: true,
errorMessage: 'Some error happened',
})
}
render() {
const { handleChange } = this
return (
<div>
<input type='file' onChange={handleChange} id='input'/>
<label htmlFor='input'> Upload </label>
{this.state.error && <span>{this.state.errorMessage}</span>}
</div>
)
}
}
class FooClosure extends Component {
render() {
return (
<div>
<Foo />
</div>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<FooClosure />
</div>
);
}
}
export default App;
Now this of course would make your FooClosure class redundant. If you needed to handle anything based off of the onChange in Foo, you can use this:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class Foo extends Component {
constructor(props) {
super(props)
this.state = {
error: false
}
}
handleChange = event => {
const { handleFooClosureMethod } = this.props.handleFooClosureMethod
handleFooClosureMethod(args)
this.setState({
error: true,
errorMessage: 'Some error happened',
})
}
render() {
const { handleChange } = this
return (
<div>
<input type='file' onChange={handleChange} id='input'/>
<label htmlFor='input'> Upload </label>
{this.state.error && <span>{this.state.errorMessage}</span>}
</div>
)
}
}
class FooClosure extends Component {
handleChange = args => {
//handle this method
}
render() {
return (
<div>
<Foo handleFooClosureMethod={this.handleChange} />
</div>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<FooClosure />
</div>
);
}
}
export default App;
Keep in mind the latter will fire every time the onChange event occurs in your Foo class.
This is helpful, but it is not entirely accurate. The problem is that either by binding it or establishing it as an anonymous function, it cannot be rebound to the new context of Foo.
class Foo extends Component {
constructor(props) {
super(props)
this.state = {
error: false
}
this.handleChange = this.props.handleChange.bind(this)
debugger
}
render() {
console.log('foo state', this.state)
return (
<div>
<input type='file' onChange={this.handleChange} id='input'/>
<label htmlFor='input'> Upload </label>
{this.state.error && <span>{this.state.errorMessage}</span>}
</div>
)
}
}
class FooClosure extends Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange;
}
handleChange() {
let self = this // this will now be Foo
debugger // local this context will be Foo
this.setState({ error: true, errorMessage: 'Some error happened'})
}
render() {
console.log('closure state', this.state)
return (
<div>
<Foo handleChange={this.handleChange} />
</div>
)
}
}
I try to get value into a input text and add it to a text area with react-bootstrap.
I know I must use ReactDOM.findDOMNode to get value with ref. I don't understand what is wrong.
Here my code :
import React from 'react';
import logo from './logo.svg';
import ReactDOM from 'react-dom';
import { InputGroup, FormGroup, FormControl, Button} from 'react-bootstrap';
import './App.css';
class InputMessages extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.GetMessage= this.GetMessage.bind(this);
this.state = {message: ''};
}
handleChange(event)
{
this.setState({message: this.GetMessage.value});
}
GetMessage()
{
return ReactDOM.findDOMNode(this.refs.message );
}
render() {
var message = this.state.message;
return(
<FormGroup >
<FormControl
componentClass="textarea" value={message} />
<InputGroup>
<FormControl type="text" ref='message' />
<InputGroup.Button>
<Button bsStyle="primary" onClick={this.handleChange}>Send
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
);
}
}
export default InputMessages;
Form Control has a ref prop, which allows us to use React Refs
Sample Code :
class MyComponent extends React.Component {
constructor() {
/* 1. Initialize Ref */
this.textInput = React.createRef();
}
handleChange() {
/* 3. Get Ref Value here (or anywhere in the code!) */
const value = this.textInput.current.value;
}
render() {
/* 2. Attach Ref to FormControl component */
return (
<div>
<FormControl ref={this.textInput} type="text" onChange={() => this.handleChange()} />
</div>
)
}
}
Hope this helps!
Add an Input ref to your form :
<FormControl inputRef={ref => { this.myInput = ref; }} />
so now you get the value like
this.myInput.value