I'm currently developing an application using React Native.
This trial app has a parent function component and a child class component.
I want to send a state value from the parent to the child using props.
even though I use setState(), the state value doesn't change...
how can I resolve my problem?
Here is the code:
Parent
import React, { useState } from "react";
import { View } from "react-native";
import Child from "../components/Child";
export default function Parent() {
const [texts, setTexts] = useState("AAA");
return (
<View>
<Child texts={texts} />
</View>
);
}
Child
import React from "react";
import { Button } from "react-native";
class Child extends React.Component {
constructor(props) {
super(props);
this.state = { texts: props.texts };
}
handleChange = () => {
const { texts } = this.props;
this.setState({ texts: "BBB" });
console.log("handleChange");
console.log(texts);
};
render() {
const { texts } = this.props;
console.log("render");
console.log(texts);
return (
<Button
title="ADD"
onPress={() => {
this.handleChange();
}}
/>
);
}
}
export default Child;
node : 12.18.3
react native : 4.10.1
expo : 3.22.3
You actually need to pass a callback function to the Child which will then set the state on the parent.
Parent
import React, { useState } from "react";
import { View } from "react-native";
import Child from "../components/Child";
export default function Parent() {
const [texts, setTexts] = useState("AAA");
return (
<View>
<Child setText={setTexts} />
</View>
);
}
Child
import React from "react";
import { Button } from "react-native";
class Child extends React.Component {
render() {
return (
<Button
title="ADD"
onPress={() => {
this.props.setText(dataYouWantToAdd);
}}
/>
);
}
}
export default Child;
You should pass a callback function to let the parent handle the change how it needs to. Just pass the data back to the parent in the callback. Try this if you still got error do let me know
parent
import React, { useState } from "react";
import { View } from "react-native";
import Child from "../components/Child";
export default function Parent() {
const [texts, setTexts] = useState("AAA");
const handleText = (val)=>{
setTexts(val)
}
return (
<View>
<Child texts={texts} handleChange={(texts)=>handleText(texts)}/>
</View>
);
}
child
import React from "react";
import { Button } from "react-native";
class Child extends React.Component {
render() {
return (
<Button
title="ADD"
onPress={() => {
this.props.handleChange(this.state.texts);
}}
/>
);
}
}
export default Child;
Related
I take photo to demonstrate, you may look at it:
My parent component is 1, grand child component place at 3, at 2 I can do some stuff because they is parent-child but I can't call function of 1 when I look from 3, any your interest, thanks!
you have to pass props from child to grandchild
here is an example (i use react native)
Parent.js
import React, { Component } from 'react';
import Child from './Child';
import { Button, Text, View } from 'react-native';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
result: 'original state'
}
}
stateUpdate(data) {
this.setState({result:data})
}
render() {
return (
<View>
<Text>parent state: {this.state.result}</Text>
<Button
onPress={() => this.stateUpdate('original state')}
title="original state"
color="darkgreen"
/>
<Child data={this.state.result} updateState={(data) => this.stateUpdate(data)} />
</View>
)
}
}
Child.js
import React, { Component } from 'react';
import GrandChild from './GrandChild';
import { Button, Text, View } from 'react-native';
export default class Child extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<Text style={{height:20}} />
<Text>child prop: {this.props.data}</Text>
<Button
onPress={() => this.props.updateState('Changed from Child')}
title="change parent state"
color="#841584"
/>
<GrandChild data={this.props.data} updateParent={(data) => this.props.updateState(data)} />
</View>
)
}
}
GrandChild.js
import React, { Component } from 'react';
import { Button, Text, View } from 'react-native';
export default class GrandChild extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<Text style={{height:20}} />
<Text>GrandChild prop: {this.props.data}</Text>
<Button
onPress={() => this.props.updateParent('change from GrandChild')}
title="change parent state"
color="darkblue"
/>
</View>
)
}
}
here is a snack
https://snack.expo.io/GsuAf65kK
or use context api.
hope it help.
I have a requirement in which I have to call a function present in a child component from parent component using React.createRef() but the problem here is that it is multilevel child.
I'm able to call a function present in 'ChildComponent1' component but not able to call a function present in 'ChildComponent2' component from 'Parent' component. Please tell me a correct way to do this.
This is my parent.js file
import React, { Component } from 'react';
import ChildComponent1 from './ChildComponent1';
class ParentComponent extends Component {
constructor(props) {
super(props);
this.childRef = React.createRef();
}
callFunctionFromChild = () => {
this.ref.current.doSomething()
}
render() {
return (
<div>
<ChildComponent1 ref={this.childRef} />
<button onClick={()=>{this.callFunctionFromChild()}}> Click Me <button>
</div>
);
}
}
export default ParentComponent;
This is my ChildComponent1.js file:
import React, { Component } from 'react';
import ChildComponent2 from './ChildComponent2';
class ChildComponent1 extends Component {
render() {
return (
<div>
<ChildComponent2 ref={this.props.ref} />
</div>
);
}
}
export default ChildComponent1;
and this is my inner ChildComponent2.js file:
import React, { Component } from 'react';
class ChildComponent2 extends Component {
doSomething = () => {
console.log("Something is done!!");
}
render() {
return (
<div>
My Child Component
</div>
);
}
}
export default ChildComponent2;
I am trying to send value of TextInput to another Class Function in console.log. My approach is when the button is pressed the value FromStr in TextInput will got passed into another class function. Here's my code
import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import receiveMessage from "./receiveMessage"
export default class WeatherProject extends Component{
constructor (props) {
super(props);
this.state={
From:'',
FromStr:'',
}
}
changeText=(From)=>{
this.setState({From})
}
changeText1=(To)=>{
this.setState({To})
}
onPress = ()=>{
this.setState({FromStr: this.state.From})
receiveMessage.receiveMessage();
}
render(){
return (
<View>
<View style={styles.inputFields}>
<TextInput placeholder="From" id="from" style={styles.fromField} onChangeText={this.changeText} />
<View style={styles.buttonStyle}>
<Button
title={"Go Back"}
color="#f194ff"
onPress={this.onPress}
></Button>
</View>
</View>
</View>
);
}
}
receiveMessage.js
import React, { Component } from "react";
export default class receiveMessage extends Component {
static receiveMessage=()=>{
console.log(this.state.FromStr)
}
}
React does not allow to pass the data between react components in this way.
Following is way to pass the data between components in React. To get more insights please follow
import React, { Component } from 'react';
class WeatherProject extends Component {
render() {
const messageToPassed = 'Hello';
return (
<div>
<ReceiveMessage message={messageToPassed} />
</div>
);
}
}
const ReceiveMessage = props => <h1>{props.message}</h1>;
export default App;
here we pass the value from sidemenu component by raising an event
App.js
class App extends React.Component {
handleSubmit = (e, data) => console.log(`my data from props`, data);
render() {
return (
<Sidemenu
onSubmit={(e, data)=>this.handleSubmit(e, data)} />
);
}
}
SideMenu.js
const Sidemenu = props => {
const { onSubmit} = props;
return (
<button onClick={(e, type)=>this.onSubmit(e, 'mydata')} />
);
}
I am trying to learn React Context and got stuck. Need help.
App.js
import React from 'react';
import Header from './components/Header';
export const MyContext = React.createContext("Default");
class App extends React.Component {
render() {
return (
<MyContext.Provider value="dark">
<Header />
</MyContext.Provider>
);
}
}
export default App;
Header/index.js
import React, { Component } from 'react'
import { MyContext } from "./../../App";
class Header extends Component {
//static contextType = MyContext;
render() {
return (
<div>
{this.context}
</div>
)
}
}
Header.contextType = MyContext;
export default Header;
Got an error MyContext is not defined.
It works when i move Header class to App.js
What am i doing wrong? Tnx for your help
There are two ways to use context either use:
1. By using context consumer :
<MyContext.Consumer>
{
contextValue => {
return <div>
{value}
</div>
}
}
<MyContext.Consumer>
2. By assigning context to a object:
static contextType = MyContext;
render(){
const {value1,value2.......} = this.context
}
For more information about Context visit the React official page.
https://reactjs.org/docs/context.html
The provider only holds the the value for you(a bit like a store). It is the consumer that makes it available to your components.
Headerjs should look like this
// Header.js
import React, { Component } from 'react'
import { MyContext } from "./../../App";
class Header extends Component {
//static contextType = MyContext;
render() {
return (
<MyContext.Consumer>
{ value => {
return <div>
{value}
</div>
}}
<MyContext.Consumer>
)
}
}
// Header.contextType = MyContext; not needed for react v16+
export default Header;
To get more power out of Context i will suggest combining with Higher Order Components. for example if what you want is a theming system
you can do this.
import React from "react";
const themes = {
dark: {
background: "#333"
},
light: {
background: "#f5f5f9"
}
};
const { Provider, Consumer } = React.createContext(themes);
export const ThemeProvider = ({ children }) => {
return <Provider value={themes}>{children}</Provider>
};
export const withTheme = theme => {
return Component => props => <Consumer>
{themes => {
return <Component {...props} style={{ ...themes[theme]}} />;
}}
</Consumer>
};
in app.js
import Header from "./Header";
import { ThemeProvider } from './Theme'
class App extends React.Component {
render() {
return (
<ThemeProvider>
<Header />
</ThemeProvider>
);
}
}
and lastly Header.js
import React, { Component } from "react";
import { withTheme } from "./Theme";
class Header extends Component {
//static contextType = MyContext;
render() {
return <h1 style={{ ...this.props.style }}>Header</h1>;
}
}
export default withTheme("dark")(Header);
You can read MY article on using context for auth for more
I have two js files Child.js and App.js.
Child.js
import React from 'react';
const Child = (props) =>{
<div>
<button onClick={props.doWhatever}>{props.title}</button>
</div>
}
export default Child;
App.js
import React, { Component } from 'react';
import './App.css';
import Child from './components/parentTochild/Child.js'
class App extends Component {
state = {
title : 'Helloooo'
}
changeWorld = (newTitle) => {
this.setState = ({
title : newTitle
});
}
render() {
return (
<div className="App">
<Child doWhatever={this.changeWorld.bind(this , 'New world')} title={this.state.title}/>
</div>
);
}
}
export default App;
While executing this code I'm getting the error mentioned in the title. I have tried to solve it. But I couldn't figure out what's the problem with this code.
When I removed <Child doWhatever={this.changeWorld.bind(this , 'New world')} title={this.state.title}/> and typed a text it showed on screen. The problem is when using the Child component.
You should return some thing from child component.
import React from 'react';
const Child = (props) =>{
return (
<div>
<button onClick={(event)=>props.doWhatever('New world')}>{props.title}</button>
</div>
);
}
export default Child;
Updated:
If you want to send a text with the event handler to you can do this :
import React, { Component } from 'react';
import './App.css';
import Child from './components/parentTochild/Child.js'
class App extends Component {
constructor(props){
super(props);
this.state={
title : 'Helloooo'
};
this.changeWorld=this.changeWorld.bind(this);
}
changeWorld = (newTitle) => {
this.setState = ({
title : newTitle
});
}
render() {
return (
<div className="App">
<Child doWhatever={this.changeWorld} title={this.state.title}/>
</div>
);
}
}
export default App;