如何从 React Native 中的另一个类组件设置状态?

时间:2021-05-11 16:43:04

标签: javascript react-native

我有问题。 我想在我成功将产品添加到购物车后,我的购物车徽章将被更新。但是我不能 setState itemCart 组件。 这是我在购物车中添加产品时的代码。 函数 _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
    }
})

仍然是类组件 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' 
    },

})

我收到的警告是:

无法在尚未安装的组件上调用 setState。这是一个空操作,但它可能表明您的应用程序中存在错误。相反,直接分配给 this.state 或定义一个 state = {};在 Home 组件中具有所需状态的类属性。

谁能帮帮我!

1 个答案:

答案 0 :(得分:0)

所以你在这里遗漏的一件小事是,

使用 new 关键字创建新组件不会将该组件挂载到渲染树中。

您应该像这样将它包含在您的 renderFoodByList 函数中

<Home ref={this.homeRef} />

然后,在 constructor 组件的 FoodByList 中,使用

创建 homeRef

this.homeRef = React.createRef();

在此 article 中详细了解 React.createRef

基本上为 Homerender 内的 FoodByList 组件分配一个引用,使您能够调用 Home 组件内的函数。

接下来,在 Home 组件的构造函数中使用 this.setSizeCart = this. setSizeCart.bind(this) 或者将 setSizeCart 函数转换为这样的箭头函数

setSizeCart = (bien) => {
    try {
        this.setState({ itemcart: bien });
        console.log("set successfully");
    } catch (error) {
        console.log(error);
    }
}

所以现在,而不是做 this.home.setSizeCart(this.state.mangmonan.length) 你应该做的 this.homeRef.current.setSizeCart(this.state.mangmonan.length)

相关问题