How to render react component onClick? - reactjs

Hello I am trying to render my PostOnWall component I made using an onClick function. The goal that every time someone clicks the button handleClick will render one new component on the screen each time. So if I click the button three times i should see three PostOnWall components rendered on my screen. Please tell me what I am doing wrong.
class Textbox extends Component {
constructor(props) {
super(props);
this.handleClick.bind(this);
this.state = {
textArea: "",
text: "",
show: false,
curTime : new Date().toLocaleString(),
};
}
handleChange(event) {
const myValue = event.target.value;
this.setState({
textArea: myValue
})
console.log(this.state)
}
handleClick= () => {
this.setState({text:this.state.textArea,
show: !this.state.show});
return (
<div>
{this.state.show && <PostOnWall PostOnWall={this.props.PostOnWall} text={this.state.text} time={this.state.curTime}/>}
</div>
);
}
showNewPost
render() {
return (
<div>
<textarea className="Textbox"
rows="2" cols="30"
type = "text"
onChange={this.handleChange.bind(this)}
value={this.state.textArea} >
</textarea>
<button className="postbutton" onClick={this.handleClick.bind(this)}>Post</button>
</div>
);
}
}
export default Textbox;

That should do the trick for you;
import React, { Component } from 'react';
class Textbox extends Component {
constructor(props) {
super(props);
this.handleClick.bind(this);
this.state = {
textArea: '',
text: '',
show: false,
curTime: new Date().toLocaleString(),
};
}
handleChange = (event) => {
const myValue = event.target.value;
this.setState({
textArea: myValue
});
}
handleClick= () => {
this.setState({
text: this.state.textArea,
show: !this.state.show
});
}
render() {
return (
<div>
<textarea
className="Textbox"
rows="2"
cols="30"
type="text"
onChange={this.handleChange.bind(this)}
value={this.state.textArea}
/>
<button
className="postbutton"
onClick={this.handleClick}
type="button"
>
Post
</button>
{
this.state.show &&
<PostOnWall
PostOnWall={this.props.PostOnWall}
text={this.state.text}
time={this.state.curTime}
/>
}
</div>
);
}
}
You should use the function called on click to change the state only. Then render (or not) the PostOnWall component based on the state value.

you need to add state which increase on click and then render the component depending on how many time the button is clicked. here the codeSandbox for what you are trying to achieve.

Related

React radio buttons wont change

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}
//...
/>

Why is this.setState not updating in my click function?

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.

how to make parent component pass prop to children only when button is clicked

I want to pass props from AddPost component to AllPosts component only when button is clicked in AddPost.
Plus how to keep on adding new posts' data(post,title,keyid) from AddPost in a object "newArray" in AllPosts every time button is clicked and this new data gets saved in allposts array and then every post is displayed by applying map function on it.
I am facing problem about how can I get new data from AddPost in newObject and continuously keep pushing this in allposts array?
AddPost.js
class Addpost extends Component {
constructor(props) {
super(props);
this.state = {
title : '',
post : '',
keyid : 0
}
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name] : event.target.value
})
}
handleClick() {
this.setState(prevState => ({
keyid : prevState.keyid + 1,
post : '',
title : ''
}));
console.log(this.state.keyid);
}
render() {
return(
<div>
<input type="text" name="title" value={this.state.title} onChange={this.handleChange} maxLength="30" placeholder="Title here" />
<input type="text" name="post" value={this.state.post} onChange={this.handleChange} maxLength="200" placeholder="Post here" />
<input type="button" onClick={this.handleClick} value="Add Post" />
<Allposts post={this.state.post} title={this.state.title} keyid={this.state.keyid} />
</div>
)
}
}
AllPosts.js
class Allposts extends Component {
constructor(props) {
super();
this.state = {
newObject : {
post : '',
title : '',
keyid : ''
},
allPosts : []
}
}
render() {
return (
this.state.allPosts.map((post) =><div>
{ post.post}{post.title}{post.keyid}
</div>
)
)
}
}
A better way to solve your problem would be to keep AllPosts and Addpost component isolated and rendered by their component Parents
post.js
class Post extends React.Component {
state: {
allPosts: []
}
addPost = (post) => {
this.setState(prev => ({allPosts: prev.allPosts.concat([post])}))
}
render() {
<>
<Addpost addPost={this.addPost}/>
<AllPosts allPosts={this.state.allPosts} />
</>
}
}
Addpost.js
class Addpost extends Component {
constructor(props) {
super(props);
this.state = {
title : '',
post : '',
keyid : 0
}
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name] : event.target.value
})
}
handleClick() {
const { keyid, post, title } = this.state;
const post = { keyid, post, title };
this.props.addPost(post)
this.setState(prevState => ({
keyid : prevState.keyid + 1,
post : '',
title : ''
}));
}
render() {
return(
<div>
<input type="text" name="title" value={this.state.title} onChange={this.handleChange} maxLength="30" placeholder="Title here" />
<input type="text" name="post" value={this.state.post} onChange={this.handleChange} maxLength="200" placeholder="Post here" />
<input type="button" onClick={this.handleClick} value="Add Post" />
</div>
)
}
}
Allposts.js
const Allposts = () => {
return (
this.props.allPosts.map((post) => (
<div>
{ post.post} {post.title} {post.keyid}
</div>
))
)
}
However if you want to pass props only after clicking, you would need to maintain a state that says clicked or not. and then pass props like
const { clicked, post, keyid, title } = this.state;
const newProp = { post, keyid, title };
<AllPost {...(clicked? newProps: {})} />

onClick function in react does`t work with conditionals

I have a question about why does not the "onClick" function work? It will only receive "You are not old enough!", when i hit the button. I use a input field.
import React, { Component } from 'react';
class App extends Component {
constructor() {
super();
this.state= {
term: 'write a number'
}
this.change = this.change.bind(this);
}
change = (event) => {
this.setState({term: event.target.value >= 18 ? <p>You are old enough!
</p> : <p>You are not old enough!</p>});
}
render() {
return (
<div style={{textAlign : "center"}}>
<input type="text"></input><br></br>
<p>Result</p><br></br>
{this.state.term}
<button type="submit" onClick={this.change}>Submit</button>
</div>
);
}
}
export default App;
If you want to validate the input on click, store the value of the input in state.
class App extends Component {
constructor() {
super();
this.state = {
term: 'write a number',
value: ''
};
}
handleChange = event => {
this.setState({
value: event.target.value
});
};
validate = () => {
this.setState({
term:
parseInt(this.state.value) >= 18
? 'You are old enough!'
: 'You are not old enough!'
});
};
render() {
return (
<div style={{ textAlign: 'center' }}>
<input
type="text"
onChange={this.handleChange}
value={this.state.value}
/>
<br />
<p>Result</p>
<br />
<p>{this.state.term}</p>
<button type="submit" onClick={this.validate}>
Submit
</button>
</div>
);
}
}
You can create a handler for the input and when you click in the button you get the value from the state.
Check it out my approach.
class App extends React.Component {
state = {
age: null,
term: 'write a number'
}
onClick = () => {
if(this.state.age) {
const output = this.state.age >= 18 ?
<p>You are old enough!</p> :
<p>You are not old enough!</p>
this.setState({
term: output
});
}
onInputHandler = (event) => {
this.setState({age: event.target.value})
}
render() {
return (
<div style={{textAlign : "center"}}>
<input type="text" onChange={e => this.onInputHandler(e)}></input><br></br>
<p>Result</p><br></br>
<button onClick={this.onClick}>Submit</button>
</div>);
}
}

React multiple button on page, to know which one clicked

I have multiple buttons on my screen and and inside same container I have another label, on click I want to show the label and then hide after few seconds.
I am controlling through this.state problem is when event fires it shows all labels and then hides all. I found few solutions like assign ids etc and array for buttons.
But issue is there can be unlimited buttons so thats not the way to go to set state for each button. Or if there is any other possible way.
export default class App extends React.Component {
constructor(props) {
super();
this.state = {
visible: false
}
}
_handleClick = () => {
this.setState({
visible: !this.state.visible
});
setTimeout(() => {
this.setState({
visible: false
});
},2000);
}
render() {
return (
<div>
<button onClick={this._handleClick}>Button 1</Text></button>
{this.state.visible && <span style={styles.pic}>
Pic
</span>
}
</div>
<div>
<button onClick={this._handleClick}>Button 2</Text></button>
{this.state.visible && <span style={styles.pic}>
Pic
</span>
}
</div>
<div>
<button onClick={this._handleClick}>Button 3</Text></button>
{this.state.visible && <span style={styles.pic}>
Pic
</span>
}
</div>
</div>
);
}
}
You need each button to have its own state... So make each button a Component!
class App extends React.Component {
render() {
return <div>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<Button>4</Button>
</div>
}
}
class Button extends React.Component {
constructor(props) {
super();
this.state = {
visible: false
}
}
_handleClick = () => {
this.setState({
visible: !this.state.visible
});
setTimeout(() => {
this.setState({
visible: false
});
}, 2000);
}
}
If there are unlimited buttons, then you can set the state like this regarding which button is clicked.
_handleClick = (id) => {
this.setState({ [id]: true })
}
id will be the unique id of each button.
Here is a simple example to show how to set the state.
https://codesandbox.io/s/k38qyv28r

Resources