I'm learning React and I'm trying to create a program with React that would take texts from two input fields and bind them. I get the input fields but the onClick function is not working.
Would appreciate if someone could point out what I'm doing wrong.
Example
<div id='root'></div>
<script type="text/babel">
class CombineText extends React.Component {
constructor(props) {
super(props);
this.state = {pretext: '', posttext:'', wholetext: '' };
}
combineText = () => {
this.setState({
wholetext: this.state.pretext + this.state.posttext
});
}
textChanged = (event) => {
this.setState({[event.target.name]: event.target.value});
}
render() {
return (
<div>
<p>{this.state.wholetext}</p>
<input type="text" id="pretext" onChange={this.textChanged} />
<input type="text" id="posttext" onChange={this.textChanged} />
<button onClick={this.combineText}>Press me</button>
</div>
);
}
}
ReactDOM.render(<CombineText />, document.getElementById('root'));
</script>
You need to make two changes,
First: use event.target.id while setting the state on change of input since name attribute is not defined on input
Second: Specify button type to be button since its by default submit and onClick on the submit button refreshes the page. Or else you could write event.preventDefault() in the combineText method to prevent the default submit action behavior
class CombineText extends React.Component {
constructor(props) {
super(props);
this.state = {pretext: '', posttext:'', wholetext: '' };
}
combineText = () => {
this.setState({
wholetext: this.state.pretext + this.state.posttext
});
}
textChanged = (event) => {
this.setState({[event.target.id]: event.target.value});
}
render() {
return (
<div>
<p>{this.state.wholetext}</p>
<input type="text" id="pretext" onChange={this.textChanged} />
<input type="text" id="posttext" onChange={this.textChanged} />
<button type="button" onClick={this.combineText}>Press me</button>
</div>
);
}
}
ReactDOM.render(<CombineText />, 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>
Related
I am trying to update my state by using a click function. However for some reason it is not updating. Could someone please explain to me what I am doing wrong?class Textbox extends
Component {
constructor(props) {
super(props);
this.handle = this.handle.bind(this);
this.state = {
text: 'jkjkljkljl'
}
}
handle(event) {
const myValue = event.target.value;
this.setState({
text: myValue
})
console.log(this.state)
}
render() {
return (
<div>
<textarea className="Textbox" rows="2" cols="30" type = "text" >
</textarea>
<button className="postbutton" onClick={this.handle.bind(this)}>Post</button>
<h1>{this.state.text}</h1>
</div>
);
}
}
export default Textbox;
Here is an updated version of your code that works.
Issue was that you were trying to set the value of the button to the state.
What you should do is setup textarea as a controlled input (have value and onChange setup as I did below) and use that value on click.
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
textArea: "",
text: "jkjkljkljl"
};
}
handle(event) {
console.log(event);
this.setState({
text: this.state.textArea
});
console.log(this.state);
}
handleChange(event) {
this.setState({ textArea: event.target.value });
}
render() {
return (
<div>
<textarea
className="Textbox"
rows="2"
cols="30"
value={this.state.textArea}
onChange={this.handleChange.bind(this)}
/>
<button className="postbutton" onClick={this.handle.bind(this)}>
Post
</button>
<h1>{this.state.text}</h1>
</div>
);
}
}
It seems you are trying to handle a form using React/JSX. There are great libraries for this purpose (React Forms).
This is the proper code:
class App extends React.Component {
constructor(props) {
super(props);
this.handle = this.handle.bind(this);
this.state = {
text: 'Static'
}
}
handleOnChange(event) {
this.setState({text: event.target.value});
}
handleSubmit(event) {
if (event.keyCode == 13) return this.sendData();
}
render() {
return (
<div>
<form onKeyUp={this.handleOnChange}>
<textarea className="Textbox"
rows="2" cols="30" type="text"
>
</textarea>
<button className="postbutton"
onClick={this.handleSubmit.bind(this)}>
Post
</button>
</form>
<h1>{this.state.text}</h1>
</div>
);
}
}
React.render(<App />, document.getElementById('app'));
In your example, you are binding the state to the root of the button and not the textarea. If you want a static example (whereas the above code changes as you type), you may simply handle the enter key via if (event.keyCode == 13) return this.sendData() and remove the onChange.
I'm learning React and am having a hard time understanding how a class component's method parameters work. In the code below the handleAddOption method (which helps with adding items upon clicking a button, it's a to-do app) - it takes 'option' as parameter - but I do not see the arguments supplied in the render method.
Similarly in the AddOption component the handleAddOption has an argument 'option' - where is this coming from?
I'm a newbie to React and to stackoverflow as well, any norms I may not have followed please point out. Thanks for the help.
class App extends React.Component {
constructor(props) {
super(props);
this.handleAddOption = this.handleAddOption.bind(this);
this.state = {
options: []
};
}
handleAddOption(option) {
if (!option) {
return 'Enter valid value to add item';
} else if (this.state.options.indexOf(option) > -1) {
return 'This option already exists';
}
this.setState((prevState) => {
return {
options: prevState.options.concat(option)
};
});
}
render() {
return (
<div>
<div>{this.state.options.map((option) => <p>{option}</p>)}</div>
<AddOption handleAddOption={this.handleAddOption} />
</div>
);
}
}
class AddOption extends React.Component {
constructor(props) {
super(props);
this.handleAddOption2 = this.handleAddOption2.bind(this);
this.state = {
error: undefined
};
}
handleAddOption2(e) {
e.preventDefault();
const option = e.target.elements.option.value.trim();
const error = this.props.handleAddOption(option);
this.setState(() => {
return { error };
});
}
render() {
return (
<div>
{this.state.error && <p>{this.state.error}</p>}
<form onSubmit={this.handleAddOption2}>
<input type="text" name="option" />
<button>Add Option</button>
</form>
</div>
);
}
}
render(<App />, document.getElementById('app'));
The arguments are being passed by the submit handler attached to the form.
You provide a function that you want called whenever there is a submit event. The form will call whatever function you provide with the arguments it usually passes in.
This happens the same way as it happens in plain JS:
const form = document.getElementById("form");
form.addEventListener("submit", e => {
e.preventDefault();
console.log("submit 1");
});
const submitHandler = e => {
e.preventDefault();
console.log("submit 2");
};
form.addEventListener("submit", submitHandler);
<form id="form">
<input type="submit" />
</form>
Consider the React example:
class MyForm extends React.Component {
constructor(props){
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
foo:""
}
}
handleSubmit(e) {
e.preventDefault();
console.log("MyForm Submit 1");
this.setState(state => ({
foo: "foo"
}));
}
render() {
/*
onSubmit will always call the function that is provided
with a submit event argument.
*/
return (
<form onSubmit={this.handleSubmit}>
<div>{this.state.foo}</div>
<input type="submit"/>
</form>
)
}
}
class MyOtherForm extends React.Component {
constructor(props){
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
foo:""
}
}
handleSubmit(e) {
e.preventDefault();
console.log("MyForm Submit 2");
this.setState(state => ({
foo: "bar"
}));
}
render() {
// Here we will pass the argument explicitly
return (
<form onSubmit={e => this.handleSubmit(e)}>
<div>{this.state.foo}</div>
<input type="submit"/>
</form>
)
}
}
const App = () => {
return(
<div>
<MyForm/>
<MyOtherForm/>
</div>
);
};
ReactDOM.render(<App/>, 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>
According to the code you provide, handleAddOption(option) is called from the handleAddOption2 function in the AddOption component.
handleAddOption2(e) {
e.preventDefault();
const option = e.target.elements.option.value.trim();
const error = this.props.handleAddOption(option);
this.setState(() => {
return { error };
});
}
You can see that option is e.target.elements.option.value.trim(). Now, where does e comes from? Tracking the source of the function above, you can see that handleAddOption2(e) is a event handler called from here:
<form onSubmit={this.handleAddOption2}>
<input type="text" name="option" />
<button>Add Option</button>
</form>
In React, event handlers (e.g. onClick/onSubmit) by default has a default event parameter embedded to its handler function. This parameter can be any name (defined by you), and the author of the code you provide named it e.
Giving you another example, say you have a button:
<button onClick={this.sayHello}>
Click me!
</button>
There is already an event param embedded to sayHello, but you can choose not to use it.
sayHello = () => {
alert('Hello!');
}
Or if you want to use it, I'll name it event instead of e here:
sayHello = (event) => {
event => alert(event.target.value)
}
Or you can choose define the event handler inline like this:
<button value="hello!" onClick={event => alert(event.target.value)}>
Click me!
</button>
class Demo extends React.Component{
constructor (){
super();
this.state = {
list : ['car','map', 'house']
}
}
inputValue(e){
var x = e.target.value;
console.log(x)
}
addValue(){
this.state.list.push();
this.setState({list: this.state.list});
}
render(){
return(
<div>
<input onChange={this.inputValue} type="text"/>
<ul>
{this.state.list.map(item => (
<li>{item}</li>
))}
</ul>
<button onClick={this.addValue.bind(this)}>Add Element</button>
</div>
)
}
}
ReactDOM.render(
<Demo/>,
document.getElementById('test')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<div id="test"></div>
Using my code, how can i push the value from <input onChange={this.inputValue} type="text"/> in list : ['car','map', 'house']. I use for this addValue function, but i can't insert the x variable from inputValue function in push() from addValue function. How to do this using my code?
You need a state value for the text-input so that your addValue() function knows what to use when its time to add a new item. The text state will be updated with anything the user types.
Working demo: https://codesandbox.io/s/magical-feynman-fze1n
import React from "react";
class Demo extends React.Component {
constructor() {
super();
this.state = {
text: "",
list: ["car", "map", "house"]
};
}
inputValue(e) {
this.setState({
text: e.target.value
});
}
addValue() {
const text = this.state.text;
this.setState({ list: [...this.state.list, text] });
}
render() {
return (
<div>
<input onChange={this.inputValue.bind(this)} type="text" />
<ul>
{this.state.list.map(item => (
<li>{item}</li>
))}
</ul>
<button onClick={this.addValue.bind(this)}>Add Element</button>
</div>
);
}
}
export default Demo;
Also, refrain from doing direct state-mutations like this.state.list.push(blah). This is against React principles and can lead to unwanted visual side-effects. If you need to reference an existing state, try to create a copy of it instead. In the case for you list, we use the spread-operator to create a shallow-copy and then added the new item to the array..
Since React is all about small components and reusability consider breaking it up into two separate components... That way, if you need a form anywhere else you can reuse it...
Here is your Demo:
class Demo extends Component {
state = { list: ['car', 'map', 'house'] };
addItem = item => {
this.setState({ list: [item, ...this.state.list] });
};
render() {
return (
<div>
<Form addItem={this.addItem} />
{this.state.list.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);
}
}
And here is the Form:
class Form extends Component {
state = { item: '' };
handleChange = event => {
this.setState({ item: event.target.value });
};
handleSubmit = event => {
event.preventDefault();
this.props.addItem(this.state.item);
this.setState({ item: '' });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type='text'
value={this.state.item}
onChange={this.handleChange}
/>
</form>
);
}
}
Live Demo: https://stackblitz.com/edit/react-611uzp
I have multiple checkbox in my React Class B.js:
<input
type="checkbox"
inline={true}
checked={this.props.checkBoxDefaultStatus}
onChange={this.handleCheckBoxClick}
/>
Now the prop checkBoxDefaultStatus is passed from parent class A.js.
A.js
this.state = {
checkBoxDefaultStatus: false
}
handleMultiSelect() {
this.setState({
checkBoxDefaultStatus: true
})
}
render() {
<B checkBoxDefaultStatus={this.state.checkBoxDefaultStatus} />
}
EDIT: Now All my child checkboxes are getting checked when I click on parent checkbox, but the issue is that my child checked boxes checked status does not change when I click on them as they are already set by parent prop. I need some way to maintain this also.
This is the behaviour I want https://stackoverflow.com/a/35218069/6574017
If you want change parent component state inside child component, then you have to pass parent component method to child component as props like below,
<B handleCheckBoxClick={this.handleMultiSelect}/>
Check below working code. I build 2 component for your scenario.
class B extends React.Component {
constructor(){
super();
this.state = {
checkBoxClick : {
1: false,
2: false
}
}
this.handleCheckBoxClick = this.handleCheckBoxClick.bind(this);
}
handleCheckBoxClick(no, event){
//console.log('no', no);
//console.log('event.target.value', event);
var checkBoxClick = this.state.checkBoxClick;
checkBoxClick[no] = !this.state.checkBoxClick[no];
this.setState({
checkBoxClick
});
var alltrue =Object.keys(checkBoxClick).every((k) =>{ return checkBoxClick[k] });
//console.log('alltrue', alltrue);
if(alltrue){
// console.log('alltrue in if : ', alltrue);
this.props.handleMultiSelect();
}
if(this.props.checkBoxDefaultStatus){
this.props.handleMultiSelect();
}
}
render(){
//console.log('this.state.checkBoxClick :', this.state.checkBoxClick);
//console.log('this.props.checkBoxDefaultStatus :', this.props.checkBoxDefaultStatus);
return(
<div>
Child component check-box <br />
<input
type="checkbox"
checked={this.props.checkBoxDefaultStatus ? this.props.checkBoxDefaultStatus : this.state.checkBoxClick[1]}
onChange={(e) => {this.handleCheckBoxClick(1, e.target.checked)}}
/> Bar 1<br />
<input
type="checkbox"
checked={this.props.checkBoxDefaultStatus ? this.props.checkBoxDefaultStatus : this.state.checkBoxClick[2]}
onChange={(e) => {this.handleCheckBoxClick(2, e.target.checked)}}
/> Bar 2<br />
</div>
);
}
}
class A extends React.Component {
constructor() {
super();
this.state = {
checkBoxDefaultStatus: false
}
this.handleMultiSelect = this.handleMultiSelect.bind(this);
}
handleMultiSelect() {
//console.log('aaaa')
this.setState({
checkBoxDefaultStatus: !this.state.checkBoxDefaultStatus
})
}
render() {
//console.log('checkBoxDefaultStatus :', this.state.checkBoxDefaultStatus);
return (
<div>
<input type="checkbox" onClick={() => {this.handleMultiSelect()}} checked={this.state.checkBoxDefaultStatus}/>
Check all<br />
<B checkBoxDefaultStatus={this.state.checkBoxDefaultStatus}
handleMultiSelect={()=>{this.handleMultiSelect()}}
/>
</div>
);
}
}
ReactDOM.render( < A / > , 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>
Please using checked prop instead of defaultChecked
like this:
<input
type="checkbox"
inline={true}
checked={this.props.checkBoxDefaultStatus}
onChange={this.handleCheckBoxClick}
/>
Its very simple.
Use event.target.checked to know the checkbox status.
Example:
HTML: <input type="checkbox" onClick={(e) => OnCheckboxClick(e)}/>
JS:
const OnCheckboxClick= (e) => {
if(e.target.checked) {
//blah blah
}
else {
//blah blah
}
}
I am new to React and need some help to my specific situation. I have a top-level app.js where I render
export default class Page extends React.Component {
constructor(props) {
super(props);
this.state = {
currentGuess: '',
historicGuess: '',
result: ''
};
}
handleCurrentGuess(event) {
console.log(event)
this.setState({currentGuess: event.target.value})
}
handleSend() {
console.log(this.state.currentGuess)
}
render() {
return (
<div className="wrapper">
<Header />
<Logic handleCurrentGuess={this.handleCurrentGuess}/>
<Result />
</div>
)
}
}
The component has to be stateful, and I enter the currentGuess value into state.
The <Logic /> looks like this:
export default function Logic(props) {
console.log(props)
return (
<div className="logic">
<form>
<input type="text" onChange={props.handleCurrentGuess}/>
<button onClick={(e) => {
e.preventDefault()
props.handleSend
}}>Send</button>
</form>
</div>
)
}
The issue now is that I cannot find documentation on how to pass both pass the function on to the AND get returned a value from the input. Most docs show onChange via the input directly, but I want to fetch the value ONLY when someone clicks on the submit button (or hits enter). So,
how do I pass the correct function to the child, and how do I get the text value back on button press within the Logic component?
If you want to console.log the state right now (for testing purposes obviously) here is the two problems with your code.
First, you are not passing your handleSend function as a prop to Logic component.
Second, on your button, you are not invoking this handleSend function in your onClick handler.
Here is a working example.
const Logic = props => (
<div className="logic">
<form>
<input type="text" onChange={props.handleCurrentGuess} />
<button onClick={props.handleSend}>Send</button>
</form>
</div>
);
class Page extends React.Component {
state = {
currentGuess: '',
historicGuess: '',
result: ''
};
handleCurrentGuess = event =>
this.setState({ currentGuess: event.target.value })
handleSend = (e) => {
e.preventDefault();
console.log(this.state.currentGuess)
}
render() {
return (
<div className="wrapper">
<Logic
handleCurrentGuess={this.handleCurrentGuess}
handleSend={this.handleSend} />
</div>
)
}
}
ReactDOM.render(<Page />, 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>
I slightly changed the code. Use some arrow functions so no need to .bind them, remove the unnecessary constructor, use class-fields, etc. I also used the function reference for onClick in the button.