I've got a few check boxes that, onClick, are pushed to state via .concat().
class App extends React.Component {
constructor() {
super()
this.state = {
selectedChoices: []
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(event) {
this.setState({
selectedChoices: [this.state.selectedChoices.concat(event.target.value)]
})
}
render() {
return(
<div>
<div onChange={this.handleClick}>
<input type="checkbox" name="choiceNumber" value="one" />
<input type="checkbox" name="choiceNumber" value="two" />
<input type="checkbox" name="choiceNumber" value="three" />
</div>
<p>{this.state.selectedChoices}</p>
</div>
)
}
}
Naturally, anytime the check box is clicked, regardless if it's .checked or not, that value is pushed to state.
I'm having some trouble finding the best way to go about this.
Above answer is correct but no need to use extra boolean "Flag".
use:
event.target.checked
Below snippet will work!
handleClick(event) {
if (!event.target.checked) {
this.setState({
selectedChoices: this.state.selectedChoices.filter(
(number) => number !== event.target.value
)
});
} else {
this.setState({
selectedChoices: this.state.selectedChoices.concat(event.target.value)
});
}
}
First, you don't have to wrap this.state.selectedChoices.concat(event.target.value) inside an array.
Second, you have to make condition if selected value has been added to selectedChoices you have to remove value from selectedChoices using filter. Else, you push value using concat just like you do.
import React from "react";
export default class App extends React.Component {
constructor() {
super();
this.state = {
selectedChoices: []
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
let flag = false;
for(const i in this.state.selectedChoices) {
if (this.state.selectedChoices[i] === event.target.value) {
flag = true;
break;
}
}
if(flag) {
this.setState({
selectedChoices: this.state.selectedChoices.filter(number => number !== event.target.value)
});
} else {
this.setState({
selectedChoices: this.state.selectedChoices.concat(event.target.value)
});
}
}
render() {
return (
<div>
<div onChange={this.handleClick}>
<input type="checkbox" name="choiceNumber" value="one" />
<input type="checkbox" name="choiceNumber" value="two" />
<input type="checkbox" name="choiceNumber" value="three" />
</div>
<p>{this.state.selectedChoices}</p>
</div>
);
}
}
here you can see how it run https://codesandbox.io/s/affectionate-diffie-0oi4t?file=/src/App.js
Related
I am trying to control my radio buttons with state so that i can add an active class for a radio button when it is clicked. Im stuck now because i need to double click to make the radio button change and after they changed once, i cant get anymore console output. Can someone see what is wrong?
import React, { Component } from 'react'
class CustomRadio extends Component {
constructor(props) {
super(props);
this.state = {
name:'',
id:'',
value:'',
onChange:'',
label:'',
validationMsg:'',
rbValue:'',
checked:''
};
}
onSelect = (e) => {
this.setState({
rbValue: e.target.value
});
//console.log(this.state.rbValue);
console.log(e.target.value);
console.log(this.props.checked);
}
// setClass = () => {
// if (this.state.rbChecked === true)
// return "active"
// else
// return "inactive"
// }
render() {
//let rbActiveClass = this.setClass();
return (
// <div className={`form-item custom-radio ${rbActiveClass}`}>
<div className={`form-item custom-radio`}>
{this.props.label &&
<label htmlFor={this.props.id}>
{this.props.label}
</label>
}
<input
type="radio"
id={this.props.id}
name={this.props.name}
value={this.props.value}
checked={this.state.rbValue === this.props.checked}
//defaultChecked={this.props.defaultChecked}
onChange={this.onSelect.bind(this)}
/>
{this.props.validationMsg &&
<span className="validation-message">
{this.props.validationMsg}
</span>
}
</div>
)
}
}
export default CustomRadio
just change component constructor:
class CustomRadio extends Component {
constructor(props) {
super(props);
this.state = {
//...
rbValue:props.checked,
//...
};
}
and also input component:
<input
//...
checked={this.state.rbValue}
//...
/>
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.
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 sending a callback function from a parent to a child component, and although the parent successfully updates it's state based on input provided to the child, it immediately reverts back to initial state, thus resulting in the browser briefly flashing the input that was provided and then displaying the initial state. What is the fix for this? Here is my code:
Parent:
class App extends Component {
constructor() {
super()
this.state = { item: '' }
this.getItem=this.getItem.bind(this);
}
getItem(val) {
this.setState({
item: val
})
console.log(this.state.item);
}
render() {
return (
<div className="App">
<Input getItem={this.getItem} />
<h2>{this.state.item}</h2>
</div>
);
}
}
Child:
class Input extends Component {
constructor(props) {
super(props)
this.state = { value: '' }
this.handleChange=this.handleChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
value: e.target.value
})
console.log(this.state.value)
}
handleSubmit(e) {
{this.props.getItem(this.state.value)};
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
<input type="text" name={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="+" />
</form>
</div>
)
}
}
I was able to solve this by using e.preventDefault() in the handleSubmit function.