React Native Synchronize parent and child state - react-native

Say i have a Parent component and a Child component which both have states with a value in common 'item'.How do i synchronise the 'item' value in the Parent and Child states ?To be more concrete, the parent could be a page of the app and the child could be a personnalized input. When i write in the input i want the page state to be updated and when the page state is updated by an external factor (say by a notification) i want the input to be updated.
export default class Parent extends Component {
constructor(props) {
super(props);
this.state={
item: 1,
}
}
render() {
return (
<Child
item = this.state.item
/>
)
}
// I want any function of this type to automatically update
// child state (and redraw child) without having to manually resynchronise
modifyItem() {
this.setState({ item: neValue })
}
}
export default class Child extends Component {
constructor(props) {
super(props);
this.state={
item: this.props.item,
}
}
// I want any function of this type to automatically update
// parent state without having to manually resynchronise
modifyItem() {
this.setState({ item: neValue })
}
}

export default class Parent extends Component {
constructor(props) {
super(props);
this.state={
item: 1,
}
}
onItemChange(item) {
this.setState({ item });
}
render() {
return (
<Child
item = this.state.item
onItemChange={this.onItemChange.bind(this)}
/>
)
}
// I want any function of this type to automatically update
// child state (and redraw child) without having to manually resynchronise
modifyItem() {
this.setState({ item: neValue })
}
}
export default class Child extends Component {
constructor(props) {
super(props);
this.state={
item: this.props.item,
}
}
// I want any function of this type to automatically update
// parent state without having to manually resynchronise
modifyItem() {
this.setState({ item: newValue })
if (this.props.onItemChange) {
this.props.onItemChange(newValue);
}
}
}

Related

How to change state of child component in react native?

I have a parent component like this:
class Parent extends Component {
onChangeState=()=>{
//I want to change it here
}
render(){
return(
<child />)
})
}
I want to change child component's state in parent. How can I do that ?
class Child extends Component {
constructor(props) {
super(props);
this.state = {
item: ''
};
}
}
In this case, you need to define the state in the parent and pass it as a prop to the child. Then, your parent has full control over the state and a state change will cause a rerender of the child and its prop will be updated. This yields in the same effect.
class Parent extends Component {
constructor(props) {
super(props);
this.state = { item: '' };
}
onChangeState = (newItem) => {
this.setState({ item: newItem })
}
return (
<Child state={this.state} />
)
}
class Child extends Component {
constructor(props) {
super(props)
}
render() {
return (
<Text>{this.props.state.item}</Text>
)
}
}

Whats the proper way to propagate changes to child components?

Using react-native I don't understand, how I have to populate changes to nested structures.
I created a simple sample.
Parent owns a Button. When pressed, the clickcount within the parent will be increased.
How do I achieve that Child' clickcount will also be increased? (in my real world scenario I want specific childs to be re-rendered. I understand that I have to change some state therefore)
Parent
var React = require('react');
import { StyleSheet, Text, View, Button } from 'react-native';
import Child from './Child';
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
clickcount: this.props.clickcount,
}
child = (<Child clickcount={this.state.clickcount}/>);
}
handlePress() {
console.log('Parent handlePress');
this.increment();
}
increment() {
this.setState({clickcount: this.state.clickcount+1});
}
render() {
return (
<View>
<Text>Parent {this.state.clickcount}</Text>
<Button
title="OK"
onPress={() => this.handlePress()}
/>
</View>
);
}
}
export default Parent;
Child
var React = require('react');
import { StyleSheet, Text, View, Button } from 'react-native';
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
clickcount: this.props.clickcount,
}
}
handlePress() {
console.log('Child handlePress');
this.increment();
}
increment() {
this.setState({clickcount: this.state.clickcount+1});
}
render() {
return (
<View>
<Text>Child {this.state.clickcount}</Text>
</View>
);
}
}
export default Child;
Currently, after 3x click the output looks like:
Parent 3
Child 0
You can pass the increment function to the child so the parent owns the click count
class Child extends React.Component {
render() {
return (
<div>
<button onClick={this.props.increment}/>
{this.props.clickCount}
</div>
)
}
}
class Parent extends React.Component {
state = {
clickCount: 0
}
increment = () => {
this.setState({ clickCount: this.state.clickCount + 1 })
}
render () {
return (
<Child increment={() => this.increment()} clickCount={this.state.clickCount}/>
)
}
}

How can I reRender Child Component from Main Component when state changes in RN 0.61?

I have two components Main and Child
export default class Main extends Component {
render() {
return (
<View>
<Child item={this.state.selectedItem} />
</View>
)
}
}
export default class Child extends Component {
state = {
newItem: null
};
organiseProductOptions() {
const { item } = this.props;
Async Request with item.ID... {
setState({ newItem: response })
}
}
componentDidMount() {
this.organiseProductOptions();
}
render() {
return (
<View>
<Text>{this.state.newItem.name}</Text>
</View>
)
}
}
Normally, this.organiseProductOptions() function is working in componentDidMount() initial state. However, When I try to rerender Child, render() method is working but componentDidMount() is not working.
How can I fire, this.organiseProductOptions() function in Child Component, when I setState selectedItem property at another time in Main Component?
Please note that, Child Component has own states.
Since Child mounts only once you can check when Child's props are changed and do your requests. Add
componentDidUpdate(prevProps) {
if (prevProps.item !== this.props.item) { // 'item' is changed
this.organiseProductOptions();
}
}
The child component re-renders when the props change but it doesn't remount. So when the child mounts it will set newItem as this.props.item, but after that newItem will never change.
The standard practice would be to just use this.props.item everywhere in your child component.

React native reload child component

I have 2 screen A and Screen B. Screen A has a sub component SomeList which loads data and i just pass the action to the subcomponent and it does the rest.Currently by design of react-navigation no action on revisit. I googled and came across https://reactnavigation.org/docs/en/navigation-events.html but not sure how to use it to reload SomeList when i navigate from ScreenB to ScreenA.
ScreenA
class ScreenA extends Component {
render() {
return (
<SomeList
loadData={this.props.actions.getAlllist}
/>
)
}
ScreenB
Class ScreenB extends Component {
someAction = () => {
this.props.navigation.navigate("ScreenA")
}
}
Due to react-native's design, I think you'd be better off passing data to your child Component.
Here's how you can do this:
class ScreenA extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
}
this.props.navigation.addListener('didFocus', this.load)
this.props.navigation.addListener('willBlur', this.unmount)
}
load = ()=>{
const _data = this.props.actions.getAlllist;
this.setState({data:_data})
}
unmount = ()=>{
this.setState({data:[]})
}
render() {
return (
<SomeList
dataArray ={this.state.data}
/>
)
}
};
If you want to fetch data each time you render something, you can use componentDidMount lifecycle method
class ScreenA extends Component {
state = {
data: [];
}
componentDidMount() {
this.setState({ data: this.props.actions.getAlllist });
}
render() {
return <SomeList loadData={this.state.data}/>;
}
So every time the ScreenA screen it's rendered it will fetch the data.

Assign to `this.state` directly or define a `state = {};` class property with the desired state in the Dashboard component

I'm passing a string value from one component class to another and try to update the state in another class
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
systemDetailsData: null,
}
}
CalledFromHeader = (systemDetailsData11) => {
this.setState({ systemDetailsData:systemDetailsData11 })
}
}
class Header extends Component {
constructor(props) {
super(props);
Dashboard_Obj = new Dashboard();
}
OnPress = () => {
Dashboard_Obj.CalledFromHeader("system data");
}
}
I'm getting this error ---> Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Dashboard component.
I want to update the state in Dashboard class using above code, Can anyone help me how to achieve this?
Call the Header component in Dashboard render method and pass a function as a prop to Header component.
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
systemDetailsData: null,
}
}
CalledFromHeader = (systemDetailsData11) => {
this.setState({ systemDetailsData:systemDetailsData11 })
}
redner(){
return <Header changeState={this.CalledFromheader} />
}
}
class Header extends Component {
constructor(props) {
super(props);
}
render(){
return(
// something view onPress handler
<Button onPress={()=>{
this.props.CalledFromHeader('Some parameters')
}} />
)
}
}