I've got a parent component with a state to detect if the user has clicked it, and the parent component uses a child component which contains an item that I want to hide if the user has clicked the parent component.
Here is the parent component:
class Parent extends Component {
constructor (props) {
super(props);
this.state = {
clicked: false
};
}
setClick = () => {
this.setState({clicked: true});
};
render() {
// ...
return (
<div onClick={this.setClick}>
<Child isClicked={this.state.clicked} />
</div>
)
}
}
Here is the child component, inside my return:
return (
<div ...>
{!props.isClicked && ( ... then render the item ... )}
</div>
)
So when the user clicks on my parent component, I am trying to change the state of clicked, and then I'm passing clicked as a prop to my child component, and inside the child component an item is rendered depending on the state of clicked. Right now, if I click on the parent component, the state is not changing and the item is still being rendered when it isn't supposed to be. What is the problem?
You need to access the props in child with this.props.isclicked
So you're child component should look like this
class Child extends React.Component<{isClicked:boolean}>{
render(){
return (
<div>
{`I am ${this.props.isClicked ? `clicked` : `not clicked` }`}
</div>
)
}
}
Related
I have an array which I want to save in my database. I have a page (parent component) and a form (child component) where my birthday input is (the one I'm saving in database). The select html elements are in the child component, and I take their values after every change. Now I need to pass recieved values from select elements back to my parent component and update the array with the recieved props. I will try to recreate my code as best as I can:
AuthenticationPage.js (Parent):
import React from 'react';
class AuthenticationPage extends Component {
constructor(props) {
super(props);
this.state({
setMonth:null
setDay:null
setYear:null
})
}
render() {
return(
<div>
<SignupForm // This is where I call my child component
onChange={(monthValue) => this.setState({ setMonth: monthValue })}
initialValues={{
dateofbirth: [
{
month: this.state.setMonth, // This one is okey but I can use onChange just to change one state
day: this.state.setDay,
year: this.state.setYear
}
]
}}
/>
</div>
)
}
}
export default AuthenticationPage;
SignupForm.js (Child):
import React from "react";
import SelectSearch from "react-select-search";
const SignupForm = (props) => (
<FinalForm
{...props}
render={(fieldRenderProps) => {
const {
// Here I render props from parent component
} = fieldRenderProps;
function monthPicker(monthValue) {
props.onChange(monthValue);
// How can I update the state of setDay and setYear states in parent component
}
return (
<Form className={classes} onSubmit={handleSubmit}>
<SelectSearch
options={month}
onChange={(monthValue) => monthPicker(monthValue)} // This is ok, I change setMonth state in parent with this function
/>
<SelectSearch
options={day}
// How to work with this, this is day input
/>
<SelectSearch
options={year}
// How to work with this, this is year input
/>
</Form>
);
}}
/>
);
export default SignupForm;
So basically I want to update states in parent component after onChange happens on select elements in my child component. I'm new to React and I can't figure this out whole day, so any help will mean a lot.
Child should receive a 'onChange' function prop. That will be called inside the child component, every time the values on the form are changed (this.props.onChange(newValue)).
The parent should hold a state of the values that will be updated accordingly (<SignupForm ... onChange={(newValue) => this.setState({ value: newValue })} />)
From parent to child you can pass data through props, but from child to parent best way is by function , i ll try to write an example below, i always code with functional component so my syntax won't be right below, but i hope you ll get the idea ...
Parent Component
class Parent extends React.Component {
constructor(props) {
super(props);
this.state({
monthValue:null
})
}
// this function send as a prop
const updateMonthValue =(value)=>{
this.state.monthValue=value
}
render() {
return <Child updateMonthValue={updateMonthValue} />;
}
}
Child Component
const Child =(props) => {
const submitHandler =(value) =>{
//here you can call the function of parent and the function in the parent will update state of parent
props.updateMonthValue(value)
}
render() {
return <h1><button onClick={()=>submitHandler("june")} /></h1>;
}
}
Hi my problem is that i have parrent component which has a checkbox. This parrent component has many child components with chechboxes too. I need to do this:
If i click parrent checkbox i also need set state child checkbox. But i shoul be able t o unclick some child chcekboxes after that,
My child ocmponent liik like this:
export class ThemePartKnowledge extends Component {
static get propTypes() {
return {
knowledge: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
this.state = {
isChecked:false,
}
}
render() {
return (
<Card className={'themePartKnowledge ml-2'}>
<Card.Header className={'d-flex flex-column flex-md-row p-x0'}>
<Form.Group controlId="formBasicCheckbox" className={'m-0 d-inline-block'}>
<Form.Check c type="checkbox" className={'my-auto'}/>
</Form.Group>
</Card.Header>
</Card>
);
}
}
My parrent controller is just sending isParrentChcecked props to this component.
How could I do this what i want? Thx for help
Edit:
So my structure look like this
Parrent
Child
Child
Child
componentDidUpdate does exactly that. Here whenever isParentChecked is changing, I am synchronising my isChecked state to parent.
componentDidUpdate(prevProps, prevState){
if(prevProps.isParentChecked !== this.props.isParentChecked){
this.setState({isChecked: this.props.isParentChecked})
}
}
I have Main Component file and use in another child component.
I have to get state of the child component.
Ex :- Home (Parent)
- Form (Child) component i have been set the value of any text box in state. So ho can i get the state value of Form component into the main component.
Generally in React (and React-Native) information is passed down from the parent component to its children. However if you need to change something in the parent component's state based on the child-component's state, you can pass a function to the child that does just that.
For example:
// Inside Parent Component
openModalFromParent() {
this.setState({ modalOpened: true });
};
// Passing Function to Child
<ChildComponent openModal={ this.openModalFromParent } />
// Inside Child Component
<TouchableHighlight onPress={ () => this.props.openModal() } />
In this example the button in the child component would trigger a function that alters the state of the parent component - hope this helps!
Pass the function as a prop to the child component
//Parent Component
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
this._handleChange = this._handleChange.bind(this);
}
_handleChange(e) {
const { name, value } = e.target;
this.setState({
[name]: value
});
}
render(){
return(){
<Form valueChange={this._handleChange} />
}
}
}
//Child Component
export default class Form extends Component {
render(){
return(){
<div>
<input type="email" name="username" onChange={(e) => this.props.valueChange()} value={username}/>
<input type="password" name="password" onChange={(e) => this.props.valueChange()} value={password}/>
</div>
}
}
}
In React, your state can only flow down from the parent to the children.
What you should do is move the state from the child to the parent and then pass the state to the child as props.
Try reading this: https://reactjs.org/docs/lifting-state-up.html
I am trying to add a className to a child component of layouts/index.js in React with Gatsby. How can I pass the className in props to be used with the component when the onClick is registered in another component?
index.js
class Template extends React.Component {
constructor(props) {
super(props)
this.state = {
navIsVisible: false,
}
this.handleNavIsVisible = this.handleNavIsVisible.bind(this)
}
handleNavIsVisible() {
this.setState({
navIsVisible: !this.state.navIsVisible
})
}
render() {
const { children } = this.props
return (
<div>
<MenuButton navIsVisible={this.handleNavIsVisible}/>
<div className="page">
...
</div>
{/* Adding the class here seems to be the best option but does not activate onClick, yet does if adding to a div with Menu contained */}
<Menu className={`${this.state.navIsVisible ? 'nav-is-visible' : ''}`}/>
</div>
)
}
}
MenuButton.js to activate the class onClick
class MenuButton extends Component {
constructor(props) {
super(props)
this.menuClick = this.menuClick.bind(this)
}
menuClick(){
this.props.navIsVisible();
}
render () {
return (
<div className="sticky-menu-button">
<span onClick={this.menuClick}>Menu</span>
</div>
)
}
}
MenuButton.propTypes = {
navIsVisible: PropTypes.func,
}
Alternatively, within Menu.js but unsure how to pass the state change to this component?
The reason it works on a div and not on your Menu component is that when you pass it to a div it adds that class "directly" to the div HTML element but when you pass it to your component it just passes it as a prop. It really depends on what you do inside the render method of the Menu component and what you return from it. If you make sure to grab that prop and attach it to whatever it renders it will work just as it did on a div.
eg:
class Menu extends Component {
render () {
return (
<div className={this.props.className}>
<p> Menu Component </p>
</div>
)
}
}
According to the React tutorial at https://facebook.github.io/react/tutorial/tutorial.html:
When you want to aggregate data from multiple children or to have two
child components communicate with each other, move the state upwards
so that it lives in the parent component. The parent can then pass the
state back down to the children via props, so that the child
components are always in sync with each other and with the parent.
This seems to contradict good OOP practices where each object maintains it own state.
When you want to aggregate data from multiple children or to have two
child components communicate with each other, move the state upwards
so that it lives in the parent component. The parent can then pass the
state back down to the children via props, so that the child
components are always in sync with each other and with the parent.
Consider a case where a Parent has two children, with a structure as follows
<Parent>
<Child1/>
<Child2/>
</Parent>
Now Child1 just has the input component, and Child2 displays what was entered in the input say
In this case if you keep the value of the input in Child1, you cannot access it from the Parent as state is local to a component and is a private property . So it makes sense to keep the property in parent and then pass it down to child as props so that both children can use it
A sample snippet
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
inputVal: ''
}
}
handleChange = (val) => {
this.setState({inputVal: val});
}
render() {
return (
<div>
<Child1 handleChange={this.handleChange} inpVal={this.state.inputVal}/>
<Child2 value={this.state.inputVal}/>
</div>
)
}
}
class Child1 extends React.Component {
render() {
return (
<div>
<input type="text" value={this.props.inpVal} onChange={(e) => this.props.handleChange(e.target.value)} />
</div>
)
}
}
class Child2 extends React.Component {
render() {
return (
<div>
{this.props.value}
</div>
)
}
}
ReactDOM.render(<Parent/>, 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"></app>