[英]How to setState from another class component in React Native?
I have a problem.我有个问题。 I want after I successfully add product to cart my shopping cart badge will be updated.
我希望在成功将产品添加到购物车后,我的购物车徽章将被更新。 But I can't setState the itemCart component.
但我不能 setState itemCart 组件。 This is code when i add products in cart.
这是我在购物车中添加产品时的代码。 Function _datmon() will do that.
Function _datmon() 会这样做。
import React, { Component } from 'react';
import {View,Text,StyleSheet,Dimensions,Image, TouchableOpacity,Modal, Button, Alert} from 'react-native';
import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview";
import { Snackbar} from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import AsyncStorage from '@react-native-community/async-storage';
import Home from '../Home';
import 'regenerator-runtime/runtime';
export default class FoodByList extends Component{
constructor(props){
super(props);
this.state={
mang:[],
dataProvider: new DataProvider ((r1,r2)=> r1!==r2),
statusInform:false,
modalVisible: false,
id:'',
gia:'',
mota:'',
soluong:1,
mangmonan:[{
id:'',
soluong:'',
}],
getArr:[],
hide: true,
}
this.home = new Home();
this.homeref = React.createRef();
}
openModalWithItem(item) {
this.setState({
ten: item.ten,
gia: item.gia,
hinhanh: item.hinhanh,
id: item.id,
mota: item.mota,
})
}
layoutProvider = new LayoutProvider(
index => {
return index;
},
(type,dim) => {
dim.width = Dimensions.get('window').width/2;
dim.height = 280;
}
)
_datmon = async()=>{
//Get array availible device
try {
const myArray = await AsyncStorage.getItem('keyOrdermonan');
if (myArray !== null) {
// We have data!!
console.log(JSON.parse(myArray));
}
} catch (error) {
// Error retrieving data
console.log(error);
}
const myArray = await AsyncStorage.getItem('keyOrdermonan');
if(myArray !=null){
this.state.getArr = JSON.parse(myArray);
//Id food currently
const check = {id:this.state.id};
var position = 0;
//Check id avalilabled in cart ?
const police = this.state.getArr.some(getA => getA.id===check.id );
if(police==true){
for(var i =0;i<this.state.getArr.length;i++){
if(this.state.getArr[i].id==this.state.id){
break;
}else{
position+=1;
}
}
this.state.getArr[position].soluong += this.state.soluong;
this.setState({mangmonan: this.state.getArr});
this.homeref.setSizeCart(this.state.mangmonan.length);
console.log('Completely udrage quanity');
}
else if(police==false){
this.setState({mangmonan: [{id: this.state.id,
soluong: this.state.soluong,
}].concat(this.state.getArr)});
this.homeref.setSizeCart(this.state.mangmonan.length);
}
}else{
this.setState({mangmonan: [{id: this.state.id,
soluong: this.state.soluong,
}]});
this.homeref.setSizeCart(this.state.mangmonan.length);
}
// Add new cart
try {
await AsyncStorage.setItem('keyOrdermonan', JSON.stringify(this.state.mangmonan));
// await AsyncStorage.removeItem('keyOrdermonan');
this.setState({modalVisible:false,soluong:1});
Alert.alert(
"Thành công",
"Đặt món thành công, vui lòng kiểm tra giỏ hàng",
[
{
text: "Kiểm tra giỏ hàng",
onPress: ()=>{this.props.navigation.navigate('cart')}
},
{
text: "Tiếp tục đặt món",
style:'cancel'
},
]
);
} catch (error) {
// Error saving data
console.log(error);
}
}
getPriceVND = (giatri) => {
const parts = giatri.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const gia = parts.join(".");
return gia;
}
rowrender = (type,item) => {
return(
<View style={styles.bgitem}>
<TouchableOpacity style={styles.wrapperitem} onPress={()=> {this.setState({modalVisible:true}),this.openModalWithItem(item)}}>
<View style={styles.wrapperimg}>
<Image source={{ uri: item.hinhanh }} style={styles.img}/>
</View>
</TouchableOpacity>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold' }}>Tên món ăn:</Text>
<Text style={styles.under}>{item.ten}</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold' }}>Giá: </Text>
<Text style={styles.under}>{this.getPriceVND(item.gia)}đ</Text>
</View>
</View>
)
}
componentDidMount(){
//set lại tittle bar
this.props.navigation.setOptions({title:this.props.route.params.tendanhmuc});
fetch("http://192.168.43.25/DemoJWT/getMonAnByList.php",{
method:'POST',
headers: {
"Accept":"application/json",
"Content-Type":"application/json"
},
body: JSON.stringify({
"IDDANHMUC" : this.props.route.params.id,
})
})
.then((reponse)=>reponse.json())
.then((reponseJson)=>{
if(reponseJson==""){
this.setState({statusInform:true});
}else{
this.setState({
mang:reponseJson,
dataProvider:this.state.dataProvider.cloneWithRows(reponseJson),
})
}
})
.catch((err)=>{
console.log(err);
})
}
render(){
return(
<View style={styles.wrapper}>
{!this.state.hide && <Home ref={this.homeref} />}
{ !this.state.dataProvider.getSize()==0 &&
<RecyclerListView
layoutProvider={this.layoutProvider}
rowRenderer={this.rowrender}
dataProvider = {this.state.dataProvider}
/>
}
{/* Thông báo khi không có món */}
<Snackbar
visible={this.state.statusInform}
onDismiss={()=>{this}}
action={{
label: 'Trở về',
onPress: () => {
this.props.navigation.goBack()
},
}}>
Hiện nhà hàng chưa có các món ăn này.
Mong quý khách thông cảm !
</Snackbar>
{/* Thông báo khi không có món */}
{/* Hiển thị khi nhấn chi tiết món ăn để đặt hàng */}
<View>
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
>
<View style={styles.modalView}>
<View style={styles.wrapperimgModal}>
<Image source={{ uri: this.state.hinhanh }} style={styles.imgModal}/>
<View style={styles.wrappername,{marginTop:15}}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Tên món ăn:</Text>
<Text >{this.state.ten}</Text>
</View>
<View style={{ flexDirection:'column' }}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Giá: </Text>
<Text>{this.getPriceVND(this.state.gia)} đ / 1 phần</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Mô tả:</Text>
<Text>{this.state.mota}</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Số lượng:</Text>
<View style={{ flexDirection:'row',marginLeft:0,marginTop:10 }}>
<TouchableOpacity style={styles.decrease} onPress={()=>{
if(this.state.soluong==1){
console.log('Không giảm nữa');
}else{
this.setState({soluong:this.state.soluong-1})
}
}}>
<MaterialCommunityIcons name='minus-circle' color="black" size={24} />
</TouchableOpacity>
<Text>{this.state.soluong}</Text>
<TouchableOpacity style={styles.increase} onPress={()=>{
if(this.state.soluong==15){
console.log('Không tăng nữa');
}
else{
this.setState({soluong:this.state.soluong+1})
}
}}>
<MaterialCommunityIcons name='plus-circle' color="black" size={24} />
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.totalbtn}>
<View style={styles.btn}>
<Button
title="Hủy"
onPress={()=>{this.setState({modalVisible:false,soluong:1})}}
/>
</View>
<View style={styles.btn2}>
<Button title="Đặt ngay"
onPress={()=>{this._datmon()}}
/>
</View>
</View>
</View>
</Modal>
</View>
{/* Hiển thị khi nhấn chi tiết món ăn để đặt hàng */}
</View>
)
}
}
const styles = StyleSheet.create({
wrapper:{
flex:1,
},
wrapperitem:{
flex:1,
},
title:{
fontSize:30,
padding:10,
fontWeight:'bold',
},
bgitem:{
flex:1,
flexDirection:'column',
padding:10,
margin:10,
borderWidth:1,
borderRadius:15,
backgroundColor:'#dddddd',
},
wrapperimg:{
width:"100%",
height:180,
alignItems:'center',
padding:5,
},
wrapperimgModal:{
width:"100%",
height:370,
padding:5,
marginLeft:10,
},
img:{
width:'80%',
height:100,
borderRadius:10,
},
imgModal:{
width:'100%',
height:150,
borderRadius:10,
},
wrappername:{
flexDirection:'column',
},
under:{
paddingLeft:10,
},
modalView: {
margin: 20,
marginTop:100,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
totalbtn:{
flexDirection:'row',
alignItems:'center',
justifyContent:'center'
},
btn:{
width:90,
marginRight:10,
},
btn2:{
width:90,
marginLeft:10,
},
decrease:{
marginRight:10,
},
increase:{
marginLeft:10
}
})
Still here is your code setSizeCart() in class component Home.js:仍然是 class 组件 Home.js 中的代码 setSizeCart():
import React, { Component } from "react";
import {StyleSheet, Alert,View, StatusBar,Linking, Text} from "react-native"
import AsyncStorage from '@react-native-community/async-storage';
import HomeScreen from "./Screen/HomeScreen";
import FavouriteScreen from "./Screen/FavouriteScreen";
import ProfileScreen from "./Screen/ProfileScreen";
import CartScreen from "./Screen/CartScreen";
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { Appbar, Snackbar,Badge } from 'react-native-paper';
import NetInfo from "@react-native-community/netinfo";
import {createDrawerNavigator} from "@react-navigation/drawer"
import { DrawerActions } from '@react-navigation/native';
import SettingScreen from "./Screen/SettingScreen";
import BookingScreen from "./Screen/BookingScreen";
import FullFood from "./Screen/FullFood";
import 'regenerator-runtime/runtime';
const Drawer = createDrawerNavigator();
export default class Home extends Component{
_isMounted = false;
constructor(props){
super(props);
this.state={
token:"",
ten:"",
statusInform:false,
searchQuery:"",
getMangAsync:[],
itemcart: 0 ,
}
this.setSizeCart = this.setSizeCart.bind(this);
}
setSizeCart (bien){
try {
this.setState({ itemcart: bien });
console.log("set thành công");
} catch (error) {
console.log(error);
}
}
_getasyc = async()=>{
try {
const key = await AsyncStorage.getItem("keyOrdermonan");
if(key!==null){
this.setState({getMangAsync:JSON.parse(key)});
this.setState({itemcart:this.state.getMangAsync.length});
}
} catch (error) {
console.log(error)
}
}
checkInternet(){
NetInfo.fetch("http://192.168.43.25/DemoJWT/checkToken.php")
.then(state=>{
console.log(state.isConnected)
if(state.isConnected==false){
this.setState({statusInform:true})
}
})
}
componentDidMount(){
this._isMounted = true;
if(this._isMounted){
this.checkInternet();
this._getasyc();
}
}
componentWillUnmount(){
this._getasyc();
// console.log("đã"+ this._isMounted)
}
_logout = async() =>{
try {
await AsyncStorage.removeItem("keyToken");
Alert.alert("Đăng xuất");
this.props.navigation.navigate('login');
} catch (error) {
console.log(error)
}
}
contact(){
Alert.alert(
"Liên hệ với chúng tôi",
"Bạn có muốn hay không?",
[
{
text: "Hủy",
style:'cancel'
},
{
text: "Đồng ý",
onPress: ()=>Linking.openURL('tel:$+84705982473')
}
]
)
}
render(){
// const {ten} = this.props.route.params
return(
<View style={{ flex:1 }}>
<StatusBar backgroundColor='#555555' barStyle="light-content" />
<Appbar style={styles.appbar}>
<Appbar.Action icon="format-list-bulleted" onPress={()=>(this.props.navigation.dispatch(DrawerActions.openDrawer()))}/>
<Appbar.Content title="GREAT FOOD" />
<Badge
visible={this.state.itemcart && this.state.itemcart >0}
size={17}
style={{ position: 'absolute', top: 5, right: 55 }}>{this.state.itemcart}</Badge>
<Appbar.Action icon="cart" onPress={()=>{this.props.navigation.navigate('cart')}}/>
<Appbar.Action icon="phone-in-talk" onPress={()=>{this.contact()}}/>
</Appbar>
<Drawer.Navigator
overlayColor="transparent"
>
<Drawer.Screen name ="home" component={HomeScreen}
options={{
drawerLabel:"Menu",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="home" color={color} size={26} />
), }}
/>
<Drawer.Screen name="profile" component={ProfileScreen}
options={{
drawerLabel:"Hồ sơ",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="account-circle" color={color} size={26} />
), }}
/>
<Drawer.Screen name="fullfood" component={FullFood}
options={{
drawerLabel:"Tất cả món ăn",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="food" color={color} size={26} />
), }}
/>
<Drawer.Screen name= "favourite" component={FavouriteScreen}
options={{
drawerLabel:"Yêu thích",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="heart-pulse" color={color} size={26} />
), }}
/>
<Drawer.Screen name= "booking" component={BookingScreen}
options={{
drawerLabel:"Đặt bàn",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="table-furniture" color={color} size={26} />
), }}
/>
<Drawer.Screen name="cart" component={CartScreen}
options={{
drawerLabel:"Giỏ hàng",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="cart" color={color} size={26} />
), }}
/>
<Drawer.Screen name="setting" component={SettingScreen}
options={{
drawerLabel:"Cài đặt",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="wrench-outline" color={color} size={26} />
), }}
/>
</Drawer.Navigator>
<Snackbar
visible={this.state.statusInform}
onDismiss={()=>{this}}
action={{
label: 'Tắt',
onPress: () => {
this.setState({statusInform:false})
},
}}>
Vui lòng kiểm tra kết nối.
</Snackbar>
</View>
)
}
}
const styles = StyleSheet.create({
wrapper:{
flex:1,
justifyContent:"center",
alignItems:'center',
},
logout:{
marginTop:50,
},
appbar:{
backgroundColor:'#555555'
},
})
And I have been received warning is:我收到的警告是:
Can't call setState on a component that is not yet mounted.无法在尚未安装的组件上调用 setState。 This is a no-op, but it might indicate a bug in your application.
这是一个无操作,但它可能表明您的应用程序中存在错误。 Instead, assign to this.state directly or define a state = {};
相反,直接分配给 this.state 或定义一个 state = {}; class property with the desired state in the Home component.
class 属性在 Home 组件中具有所需的 state。
Can anyone help me!谁能帮我!
So one small thing you are missing here is that,所以你在这里缺少的一件小事是,
Creating a new component using the new
keyword is not going to mount that component into the render tree.使用
new
关键字创建新组件不会将该组件安装到渲染树中。
You should include it inside the render
function of your FoodByList
like this您应该像这样将它包含在
FoodByList
的render
function 中
<Home ref={this.homeRef} />
Then, in the constructor
of your FoodByList
component, create the homeRef
using然后,在
FoodByList
组件的constructor
homeRef
,使用
this.homeRef = React.createRef();
More on React.createRef
in this article .更多关于
React.createRef
在这篇文章中。
Basically assigning a ref to the Home
component inside the render
of FoodByList
gives you the ability to call the functions inside the Home
component.基本上,在
FoodByList
的render
中将 ref 分配给Home
组件使您能够调用Home
组件内的函数。
Next, in Home
component's constructor use this.setSizeCart = this. setSizeCart.bind(this)
接下来,在
Home
组件的构造函数中使用this.setSizeCart = this. setSizeCart.bind(this)
this.setSizeCart = this. setSizeCart.bind(this)
or else convert the setSizeCart
function into an arrow function like this this.setSizeCart = this. setSizeCart.bind(this)
或者像这样将setSizeCart
function 转换为箭头 function
setSizeCart = (bien) => {
try {
this.setState({ itemcart: bien });
console.log("set successfully");
} catch (error) {
console.log(error);
}
}
So now, instead of doing this.home.setSizeCart(this.state.mangmonan.length)
you should be doing this.homeRef.current.setSizeCart(this.state.mangmonan.length)
所以现在,而不是这样做
this.home.setSizeCart(this.state.mangmonan.length)
你应该这样做this.homeRef.current.setSizeCart(this.state.mangmonan.length)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.