I've been trying to send a call back to parent component C from child component A to set state in parent C! This state will be sent to another child component B. I have a link component in A which calls the component in B but the child component needs the state from parent component and when I click on the link in A the call Back is not being called but I want it to be called.
Class C extends react.Component
{
constructor(props: any)
{
super(props);
this.state={
somestate: '',
}
}
CallBack(somestate:string)
{
this.Setstate({somestate, somestate},()=>{console.log(this.state.somestate);});
}
render()
{
return(
<A CallBack={this.CallBack} />
<Route path='/somestate' >
<B somestate={this.state.somestate} />
</Route>
)
}
}
Class A extends React.Component
{
constructor(props: any)
{
super(props);
}
callback()
{
this.props.CallBack();//causing errror when i click Link tag
}
render()
{
return(
<Link to='/somestate'>
<button onClick={this.callback()}>click me</button>
</Link>
)
}
}
Class B extends React.Component
{
constructor(props: any)
{
super(props);
}
render()
{
return(
<div>
this.props.somestate;
</div>
)
}
}
I'm not able to call the call back in props. I'm guessing we cant use call back to parent and link at the same time. So how to actually use it.
According to the React Router documents you should pass others props like onClick as bellow:
<Link to="/somestate" onClick={this.callback} className="some-classname">Click me</Link>
Also you can pass className so to shape the link as you want.
Related
In my situation I have a root component called App.
Inside my App component render function I have two other react components. ModalWrapper is the first component and it has a method called closeModal() which I would like to be able to call from within its child component AddUser. Is there anyway to pass this method down to addUser without moving the AddUser call to the ModalWrapper render function?
render() {
return (
<div>
<ModalWrapper title="Add Member" buttonText="Add Member">
<AddUser />
</ModalWrapper>
<div>
)
}
class Parent extends Component {
constructor(props){
super(props);
this.closeModal = this.closeModal.bind(this);
}
closeModal(){
alert('close Modal');
}
render(){
return(
<div>
<ChildComponent closeModal = {this.closeModal} />
</div>
);
}
}
class ChildComponent extends Component {
constructor(props){
super(props);
}
componentDidMount(){
this.props.closeModal();
}
render(){
return(<div> </div>);
}
}
Let's say you have parent component and you define a function in parent component and want to use that function in to the child component. You can use parent component function in to child component by passing it via props. and call parent function in child component via props.
I'm new to React and still learning.
I'm trying to pass data from child to grandparent. So far I reach to parent and I`m stuck.
Child component:
export class Child extends React.Component{
constructor(props) {
super(props);
this.state= {
counterChild: 5
}
}
render() {
return(
<div>
<span>Child: {this.state.counterChild}</span><br />
<button onClick={this.props.data(this.state.counterChild)}>Click me</button>
</div>
);
}
}
Parent component:
export default class Parent extends React.Component{
constructor(props){
super(props);
this.state= {
counterParent: 0
}
}
updateParent(value) {
return() => {
this.setState({
counterParent: value
});
}
}
componentWillMount(){
this.props.data(this.state.counterParent)
}
render(){
return(
<div>
<span>Parent: {this.state.counterParent}</span>
<Child data={this.updateParent.bind(this)}/>
</div>
);
}
}
in child component i use a button
and here i guess i have to use componentWillMount in order to send to grandparent..but it does not reach
Grandparent component:
export default class Grandparent extends React.Component{
constructor(props){
super(props);
this.state = {
counterGrandparent: 0
}
}
updateGrandparent(value){
return() => {
this.setState({
counterGrandparent: value
});
}
}
render(){
return(
<div>
<span>Grandparent: {this.state.counterGrandparent}</span>
<Parent data={this.updateGrandparent.bind(this)}/>
</div>
);
}
}
What did I do wrong here?
As you may have figured out, data is passed down the component tree in the form of props, and up in the form of prop callback functions. When something happens in a child, you call the callback to inform the parent. The parent then updates its state and passes the new state to the child as a prop.
In your case, you have three nested components, each with their own state. Typically, only a parent "container" component will have state, and child components will be stateless. So let's remove the state from the Child and Parent components. The Child component interacts with the user with a button, so whenever the button is pushed, the event handler is called and the data flows up the tree using callbacks. I added some borders and padding to make the nesting clear:
Part of the problem lies in the onClick handler on your button. Event handlers should be function references, but you have used a function call. So your child might be like below. Note the counter prop that receives the current state, and the updateParent prop that allows the Child to update the Parent.
import React from 'react';
const boxStyle = {
border: '1px solid red',
padding: '5px'
};
export class ChildWithButton extends React.Component {
handleClick(event) {
this.props.updateParent(this.props.counter + 1);
}
render() {
return(
<div style={boxStyle}>
<div>Child: {this.props.counter}</div>
<button onClick={this.handleClick.bind(this)}>
Add 1
</button>
</div>
);
}
}
The Parent component passes the current state down in the counter prop, and lets the Child component change the state by calling the updateParent callback that it received as a prop:
export class Parent extends React.Component{
updateParent(value) {
this.props.updateGrandparent(value);
}
render() {
return(
<div style={boxStyle}>
<div>Parent: {this.props.counter}</div>
<ChildWithButton
counter={this.props.counter}
updateParent={this.updateParent.bind(this)} />
</div>
);
}
}
The Grandparent component holds the state, passing it down to the Parent in counter and allowing it to update it with updateGrandparent. It should be noted that Grandparent has no knowledge of Child, only of Parent.
export default class Grandparent extends React.Component {
constructor(props) {
super(props);
this.state = {counter: 5};
}
updateGrandparent(value){
this.setState({counter: value});
}
render() {
return (
<div style={boxStyle}>
<div>Grandparent: {this.state.counter}</div>
<Parent
counter={this.state.counter}
updateGrandparent={this.updateGrandparent.bind(this)} />
</div>
);
}
}
You should avoid using componentWillMount as it will be removed in a future version of React.
You should also name the function you pass down in props something other than data. Function names are typically verbs.
There was more than one thing wrong with your code, so I hope this answers your question.
this is my parent component
class App extends Component {
constructor()
{
super();
this.state={counter:1,yourid:'',yourname:'',yourgender:''};
this.handleLogin=this.handleLogin.bind(this);
this.userview=this.userview.bind(this);
this.going=this.going.bind(this);
}
going(id,name,gender)
{
console.log("THIS IS DONE BY REACT GEEK:",id,name,gender);
this.setState({yourid:id,
Yourname:name,
Yourgender:gender});
}
this is my app.js render funtion
<Login passingvalue={this.going} />
<MessageView LoggedInUser={this.going} />
and here is my first child components from where i send values
export default class Login extends Component {
constructor(props)
{
super(props);
this.state={
id:'',name:'',gender:''
}
this.show = this.show.bind(this);
this.sendingvalue=this.sendingvalue.bind(this)
}
sendingvalue()
{
this.props.passingvalue(this.state.id,this.state.name,this.state.gender);
// console.log('passing',Id);
console.log('hello this is going ',
this.state.id,
this.state.name,
this.state.gender)
}
and again here is my second child component where i want these values
export default class Messageonline extends Component {
constructor(props)
{
super(props);
this.state = {Id:this.props.LoggedInUser.yourid,
Name:this.props.LoggedInUser.yourname,
Gender:this.props.LoggedInUser.yourgender};
}
render() {
return (
<div className="messageshow">
<div className="row">
<div className="col-lg-10 "id="message_show">
<h3>Inbox</h3>
</div>
<div className="col-lg-2" id="online_user" >
<h3>online Users</h3>
<span>{this.state.Id}</span>
<br/>
<span>{this.state.Name}</span>
<br/>
<span>{this.state.Gender}</span>
</div>
</div >
</div>
there is any mistake thats why i cannot get those values in my second child..whats is that mistake i dont know ..tell me whats this mistake i want to fix that as soon as possible..thanks
Looks like you are passing the going method as the LoggedInUser prop to your MessageView component:
<MessageView LoggedInUser={this.going} />
You are probably looking to pass a user object instead.
Something like this:
<MessageView LoggedInUser={{
yourid: this.state.yourid,
yourname: this.state.yourname,
yourgender: this.state.yourgender
}} />
I have an issue with React Router v.4. When a route is matched in the parent component and the child component is rendered, the componentDidMount method of the child triggers the showAlbum method passed to it by the parent.
However, though the showAlbum method is triggered, the setState method inside it does not update the state of the parent. When the child component is unmounted, the showAlbum method works correctly, just as it does on the subsequent calls.
Any idea where do I go wrong?
Thank you!
Parent component:
export default class AlbumContainer extends Component {
constructor(props) {
super(props)
this.state = {
showAlbum: false
}
}
showAlbum() {
this.setState({
showAlbum: !this.state.showAlbum
})
}
render() {
return (
<section className="border">
<div className="u-innerContainer">
<Route path='/:linkName' render={ (props)=><Album showalbum={ this.showAlbum.bind(this) }/> } />
</div>
</section>
)
Child component:
export default class Album extends Component {
render() {
return (
<section>
<div className="u-innerContainer">
<Link to="/">Back</Link>
<h3>{ 'title' }</h3>
<section>{ 'content' }</section>
</div>
</section>
)
}
componentDidMount() {
this.props.showalbum()
}
componentWillUnmount() {
this.props.showalbum()
}
}
I am sorry, I haven't got time to verify the solution, but your problem can be caused by setting of state based on previous state value.
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
Try to set new state by this way:
showAlbum() {
this.setState(prevState => ({
showAlbum: !prevState.showAlbum
}));
}
Please add constructor in Child component :
constructor(props) {
super(props)
}
class Parent extends React.Component{
constructor(props){
super(props);
this.clicked = this.clicked.bind(this);
}
getChildrenValues(){
console.log("Children values");
}
render(){
return <div>
Parent
<Component1>
<Component2>
<Child />
</Component2>
</Component1>
</div>
}
}
class Child extends React.Component{
constructor(props){
super(props);
this.clicked = this.clicked.bind(this);
}
clicked(){
this.props.dispatch({type: "InvokeParent"});
}
render(){
return <div>
<button onClick = {this.clicked}>Click Here</button>
</div>
}
}
how to invoke getChildrenValues function from "Child" component. I am trying to get all children values from parent component and submit but I do not know how to trigger that function in redux. In flux I used to do addChangeListener and trigger that function.
Just based on your example, I would say this situation won't involve redux at all. Redux is a tool for managing global state. Nothing in this example is touching state.
For this example code to work pass your method down as a prop and invoke it on click. This can be messy if depending on how nested the child component is.
class Parent extends React.Component{
constructor(props){
super(props);
this.clicked = this.clicked.bind(this);
}
getChildrenValues(){
console.log("Children values");
}
render(){
return <div>
Parent
<Component1>
<Component2>
<Child invokeParent={this.getChildrenValues} />
</Component2>
</Component1>
</div>
}
}
class Child extends React.Component{
constructor(props){
super(props);
this.clicked = this.clicked.bind(this);
}
clicked(){
this.props.dispatch({type: "InvokeParent"});
}
render(){
return <div>
<button onClick = {this.props.invokeParent}>Click Here</button>
</div>
}
}