Neha
Neha

Reputation: 185

pass multiple props by react navigation

I am new to react-native and trying to make a GSTCalculator App. I take values from the user on calculator screen and show calculated values on Result screen. My problem is that the calculated values don't show up immediately on the Result screen. I have even used async and await. But it only shows first calculated value.

calculate = async() => {
    await this.calculateSum();
    this.props.navigation.navigate('Result', {prodCost: this.state.prodCost,
        mfdProfitMargin: this.state.mfdProfitMargin, mCost: this.state.mCost, whProfit: this.state.whProfit,
        rtProfit: this.state.rtProfit, cgst: this.state.cgst, sgst: this.state.sgst, igst: this.state.igst,
        igstV: this.state.igstV, m2wV: this.state.m2wV, w2rT: this.state.w2rT, whProfitV: this.state.whProfitV,
        cgstV: this.state.cgstV, sgstV: this.state.sgstV, w2rV :this.state.w2rV, rtProfitV: this.state.rtProfitV })
}

calculateSum = () => {
    this.setState({mCost: Number(this.state.prodCost) + Number(this.state.mfdProfitMargin)}); 
    this.setState({igstV: (Number(this.state.mCost)*Number(this.state.igst))/100});
    this.setState({m2wV: Number(this.state.mCost) + Number(this.state.igstV)});
    this.setState({whProfitV: (this.state.m2wV)*Number(this.state.whProfit)/100});
    this.setState({w2rT: Number(this.state.m2wV) + Number(this.state.whProfitV)});
    this.setState({cgstV: (this.state.w2rT)*Number(this.state.cgst)/100});
    this.setState({sgstV: (this.state.w2rT)*Number(this.state.sgst)/100});
    this.setState({w2rV: Number(this.state.w2rT) + Number(this.state.cgstV) + Number(this.state.sgstV)});
    this.setState({rtProfitV: (this.state.w2rV)*Number(this.state.rtProfit)/100});
}

export default class Result extends Component {

constructor(props) {
    super(props);
    this.state = { pCost: this.props.navigation.state.params.prodCost, pMargin: this.props.navigation.state.params.mfdProfitMargin,
                   mCost:this.props.navigation.state.params.mCost, igstP: this.props.navigation.state.params.igst,
                   igstV: this.props.navigation.state.params.igstV, cgstP: this.props.navigation.state.params.cgst,
                   cgstV: this.props.navigation.state.params.cgstV, sgstP: this.props.navigation.state.params.sgst,
                   sgstV: this.props.navigation.state.params.sgstV, m2wV: this.props.navigation.state.params.m2wV, 
                   whProfit: this.props.navigation.state.params.whProfit, whProfitV: this.props.navigation.state.params.whProfitV,
                   w2rT: this.props.navigation.state.params.w2rT, w2rV: this.props.navigation.state.params.w2rV,
                   rtProfit:this.props.navigation.state.params.rtProfit, rtProfitV: this.props.navigation.state.params.rtProfitV 
                 }
}

render() {
    return(
        <View>
            <ImageBackground source={require('../Assets/login.jpg')} style={Styles.bgImage}>
                <ScrollView contentContainerStyle={GStyle.container}>
                    <View>
                        <Text style={[Styles.heading, {marginTop: 20}]}>Manufacturer to Wholesaler:</Text>
                        <View style={GStyle.inputView}>
                            <Text style={[GStyle.text, {marginTop:10}]}>Production Cost</Text> 
                            <Text style={GStyle.resultText}>{this.state.pCost}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Profit Margin</Text>
                            <Text style={GStyle.resultText}>{this.state.pMargin}</Text>
                        </View>

                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Manufacture Cost</Text>
                            <Text style={GStyle.resultText}>{this.state.mCost}</Text>
                        </View>
                        <View style={GStyle.inputView}>     
                            <Text style={GStyle.text}>IGST({this.state.igstP}%)</Text> 
                            <Text style={GStyle.resultText}>{this.state.igstV}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Invoice Value</Text> 
                            <Text style={GStyle.resultText}>{this.state.m2wV}</Text>
                        </View>
                    </View>
                    <View>
                        <Text style={[Styles.heading, {marginTop: 20}]}>Wholesaler to Retailer:</Text>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Cost to Wholesaler</Text> 
                            <Text style={GStyle.resultText}>{this.state.m2wV}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Profit Margin({this.state.whProfit}%)</Text> 
                            <Text style={GStyle.resultText}>{this.state.whProfitV}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Total</Text> 
                            <Text style={GStyle.resultText}>{this.state.w2rT}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>CGST({this.state.cgstP}%)</Text> 
                            <Text style={GStyle.resultText}>{this.state.cgstV}</Text> 
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>SGST({this.state.sgstP}%)</Text> 
                            <Text style={GStyle.resultText}>{this.state.sgstV}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Invoice Value</Text> 
                            <Text style={GStyle.resultText}>{this.state.w2rV}</Text>
                        </View>  
                    </View>
                    <View>
                        <Text style={[Styles.heading, {marginTop: 20}]}>Retailer to Consumer:</Text>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>Cost to Retailer</Text> 
                            <Text style={GStyle.resultText}>{this.state.w2rV}</Text>
                        </View>
                        <View style={GStyle.inputView}>
                            <Text style={GStyle.text}>ProfitMargin({this.state.rtProfit}%)</Text> 
                            <Text style={GStyle.resultText}>{this.state.rtProfitV}</Text>
                        </View>   
                    </View>
                </ScrollView>
            </ImageBackground>
        </View>
    );
}

}

Upvotes: 0

Views: 1804

Answers (1)

Andrew
Andrew

Reputation: 28539

There is a lot of setting of state going I think we can reduce it and there is a little refactoring we can do to make your code easier to read.

Constructor

You are typing the same thing over and over again and it makes your constructor much harder to read than it needs to be.

In this example we have taken the the value this.props.navigation.state.params and set it to it's own variable. This means you don't have to keep typing the this.props.navigation.state.params over and over and over again.

constructor(props) {
  super(props);
  const params = this.props.navigation.state.params
  this.state = { 
    pCost: params.prodCost, 
    pMargin: params.mfdProfitMargin,
    mCost:params.mCost, 
    igstP: params.igst,
    igstV: params.igstV, 
    cgstP: params.cgst,
    cgstV: params.cgstV, 
    sgstP: params.sgst,
    sgstV: params.sgstV, 
    m2wV: params.m2wV, 
    whProfit: params.whProfit, 
    whProfitV: params.whProfitV,
    w2rT: params.w2rT, 
    w2rV: params.w2rV,
    rtProfit:params.rtProfit, 
    rtProfitV: params.rtProfitV 
  }
}

If we use spread operator we can make this even easier, that is if you are willing to use the same name as in the object that you are passing.

constructor(props) {
  super(props);
  this.state = { 
    ...this.props.navigation.state.params 
  }
}

However, if you use this method then you will find that some of the unique names you have chosen will be gone, replaced by the ones that are in the object that you are passing.

I am assuming that you would go with the first option (as it doesn't change the names) so I will base my next refactors on that.

Calculate Sum

There are too many setStates here, It takes time for state to set, so you could be using old values in your subsequent calculations so it is best not to use setState until you have performed all your calculations. If the values for each setState depend on the previous values then you could do something like this, only using values from the initial state where necessary.

calculateSum  () => {
  let mCost = Number(this.state.prodCost) + Number(this.state.mfdProfitMargin);
  let igstV = mCost * Number(this.state.igst) / 100;
  let m2wV = mCost + igstV;
  let whProfitV = m2wV * Number(this.state.whProfit)/100;
  let w2rT = m2wV + whProfitV;
  let cgstV = w2rT * Number(this.state.cgst)/100;
  let sgstV = w2rT * Number(this.state.sgst)/100;
  let w2rV = w2rT + cgstV + sgstV;
  let rtProfitV = w2rV * Number(this.state.rtProfit)/100;
  return { mCost, igstV, m2wV, whProfitV, w2rT, cgstV, sgstV, w2rV, rtProfitV }
}

Here I return an object with all the updated values, that can be saved to state if we so choose.

Calculate

As the calculateSum function now returns an object with all the value that you want you could do something like this. We take the sum object that we just calculated and using a spread operator set all those objects to state. We then use a callback on the setState function to then navigate to the next page, using the spread operator again to capture all the values that in state.

calculate = () => {
  let sum = this.calculateSum();
  this.setState({...sum}, () => {
    this.props.navigation.navigate('Result', {...this.state })
  });
}

However if these values don't need to saved to state and just passed to the next screen, we could update the calculate function to something like this

calculate = () => {
  let sum = this.calculateSum();
  this.props.navigation.navigate('Result', {...this.state, ...sum })
}

I hope this helps you.

For more information on the spread operator in javascript see this article https://zendev.com/2018/05/09/understanding-spread-operator-in-javascript.html

For more information on setting state check out both of these articles https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0 https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296

Upvotes: 2

Related Questions