0

I have 4 input fields as below. name,count,amount,price. And two text fields, commission and total.

If user enter values at price and count then amount(price * count) should be calculated. If user enters values at price and amount then count (amount / price) should be calculated. In both cases, commission=0.02*amount and total=amount+commission should be updated.

So, I tried below code snippet as a start for updating amount and commission based on price. But it is not updating.

//App.js

import React from "react";
import App1 from "./src/screens/createCoin.jsx";
import * as Font from "expo-font";

export default function App() {
  return <App1 />;
}

//createCoins.jsx

import React, { Component, useState } from "react";
import {
  Container,
  Header,
  Content,
  H1,
  Text,
  Form,
  Item,
  Input,
} from "native-base";

export default function createCoins() {
  const [name, setName] = useState("");
  const [price, setPrice] = useState("");
  const [amount, setAmount] = useState("");
  const [commission, setCommission] = useState("");
  const [count, setCount] = useState("");

  updateDetails = (text, type) => {
    console.log("came to update Details...");
    if (type === "price") {
      const price = parseFloat(text);
      setPrice(price);
      setAmount(price * count);
      setCommission(amount * 0.002);
    }
  };

  return (
    <Container>
      <Header />
      <Content>
        <Form>
          <Item>
            <Input
              placeholder="coin name"
              onChangeText={(text) => setName(text)}
            />
          </Item>
          <Item>
            <Input
              placeholder="number of coins"
              onChangeText={(text) => setCount(count)}
            />
          </Item>
          <Item>
            <Input
              placeholder="Amount Invested"
              onChangeText={(text) => setAmount(amount)}
            />
          </Item>

          <Item last>
            <Input
              placeholder="coin price"
              onChangeText={(text) => updateDetails(text, "price")}
            />
          </Item>
        </Form>
        <Text>Commission: {commission}</Text>
        <Text>Total Amount: {commission + amount}</Text>
      </Content>
    </Container>
  );
}

Can you please suggest.

After changing the code of createCoin.jsx as below. The text field "total amount" is getting updated but how to update the input field amount? I tried adding attribute value={state.amount} to it but didn't work as getting error as invalid prop.

import React, { Component, useState } from "react";
import {
  Container,
  Header,
  Content,
  H1,
  Text,
  Form,
  Item,
  Input,
} from "native-base";

export default function createCoins() {
  const [name, setName] = useState("");
  //const [price, setPrice] = useState("");
  //const [amount, setAmount] = useState("");
  //const [commission, setCommission] = useState("");
  //const [count, setCount] = useState("");
  const [state, setState] = useState({
    price: 0,
    amount: 0,
    commission: 0,
    count: 0,
  });

  /*const updatePrice = (value) => {
    console.log("came to update Details...");
    if (count) {
      setPrice(value);
      setAmount(value * count);
    }
  };*/

  updateDetails = (text, type) => {
    console.log("came to update Details...");
    if (type == "count") {
      setState({
        ...state,
        count: text,
      });
    }
    if (type === "price") {
      console.log("came inside price");
      const price = parseFloat(text);
      setState({
        ...state,
        price: price,
        amount: price * state.count,
        commission: state.price * state.count * 0.002,
      });
      //setPrice(price);
      //setAmount(price * count);
      //setCommission(amount * 0.002);
      console.log("price:" + price);
      console.log(state.amount);
      console.log(state.commission);
    }
  };

  return (
    <Container>
      <Header />
      <Content>
        <Form>
          <Item>
            <Input
              placeholder="coin name"
              onChangeText={(text) => setName(text)}
            />
          </Item>
          <Item>
            <Input
              placeholder="number of coins"
              onChangeText={(text) => updateDetails(text, "count")}
            />
          </Item>
          <Item>
            <Input
              placeholder="Amount Invested"
              value={state.amount}
              onChangeText={(text) => updateDetails(text, "amount")}
            />
          </Item>

          <Item last>
            <Input
              placeholder="coin price"
              onChangeText={(text) => updateDetails(text, "price")}
            />
          </Item>
        </Form>
        <Text>Commission: {state.commission}</Text>
        <Text>Total Amount: {state.commission + state.amount}</Text>
      </Content>
    </Container>
  );
}

output

uday
  • 569
  • 1
  • 6
  • 16

2 Answers2

1

Here's what I did

import React, { Component, useState, useEffect, useRef } from "react";
import {
  Container,
  Header,
  Content,
  H1,
  Text,
  Form,
  Item,
  Input,
} from "native-base";

export default function createCoins() {
  const [name, setName] = useState("");
  const [amount, setAmount] = useState("");
  const [count, setCount] = useState("");
  const [price, setPrice] = useState("");
  const [commission, setCommission] = useState("");
  // used to regulate when calculations are made
  const [ focusedInput, setFocus ] = useState(null)

  // run an effect when price, count, or amount changes
  useEffect(()=>{
    // if price and count exist and user isnt changing amount, calculate amount
    if(price && count && focusedInput !== 'amount'){
      setAmount( price * count );
    }
    // if price and count exist and user isnt changing count, calculate count
    else if(price && amount && focusedInput !== 'count'){
      setCount( amount / price )
    }
  },[price,count,amount])
  // when amount changes, update commission and total
  useEffect(()=>{
    if(isNaN(amount))
      setCommission('')
    if(amount)
      setCommission( amount * 0.002);
  },[amount])
  
  return (
    <Container>
      <Header />
      <Content>
        <Form>
          <Item>
            <Input
              placeholder="coin name"
              onChangeText={setName}
              keyboardType="decimal-pad"
            />
          </Item>
          <Item>
            <Input
              placeholder="number of coins"
              onChangeText={text => setCount(parseFloat(text))}
              keyboardType="decimal-pad"
              value={count.toString()}
              onFocus={()=>setFocus("count")}
            />
          </Item>
          <Item>
            <Input
              placeholder="Amount Invested"
              onChangeText={text => setAmount(parseFloat(text))}
              keyboardType="decimal-pad"
              value={amount.toString()}
              onFocus={()=>setFocus("amount")}
            />
          </Item>

          <Item last>
            <Input
              placeholder="coin price"
              onChangeText={text=>setPrice(parseFloat(text))}
              keyboardType="decimal-pad"
              value={price.toString()}
              onFocus={()=>setFocus("price")}

            />
          </Item>
        </Form>
        <Text>Commission: {commission}</Text>
        <Text>Total Amount: {commission +amount}</Text>
      </Content>
    </Container>
  );
}

focusedInput exists to prevent the auto calculation of a value when its in focused (being changed). Without the focusedInput conditional, if price and count or amount existed, then the third value would be derived from the two values, even when you tried to change the third.

For an example, if you tried to edit the count textInput field while price and amount exists, the count textfield would overriden by setCount(amount/price) before you could type your next character.

By verifying that the field is not in focus before auto calculating its value, this undesired effect is avoided

PhantomSpooks
  • 2,877
  • 2
  • 8
  • 13
0

You need to have separate functions to calculate based on the input value like

const updatePrice = (value) => {
  if (count) {
    setPrice(value);
    setAmount(value * count);
    setCommission(value * count * 0.02); // do not use amount here directly as it is only calculated in the next render cycle
  }
}

In your Input field you change the onChange-Method to onChangeText={updatePrice}.

By the way you can remove the (text) => as the signature (parameter) of the onChangeText and the method are identical. Otherwise you will create an instance of the function on each render. This is for performance/memory optimization.

Christian
  • 4,596
  • 1
  • 26
  • 33
  • I treid this, but still not updating. My code with your changes: https://codeshare.io/2jpK7R – uday Jun 01 '21 at 09:22
  • this was only an example, you have to set all values based on the input. I have modified my answer. – Christian Jun 01 '21 at 11:58
  • yeah value is getting updated in the state but the text field for amount is not getting updated. I tried setting value attribute but getting error as invalid props – uday Jun 01 '21 at 12:25
  • you need to convert the string to number and vice versa to calculate with it and show it in the text field. Probably native-base expects string but you need to calculate with numbers. For error messages you should show the complete message as it is showing the reason – Christian Jun 01 '21 at 13:02
  • calculation is having no issues. It is updating the text fields(last two) as you can see in the above image I added now. But, the input field value "Amount Invested" is not getting updated. I tried value,defaultValue setting to {state.amount} but not changing the data. – uday Jun 01 '21 at 13:07
  • Take a look at my answer. If you have any questions, comment and I will answer asap – PhantomSpooks Jun 01 '21 at 13:24
  • what is the use of setFocus here? – uday Jun 01 '21 at 16:21
  • Without knowing which input is in focus, if the other two values existed, then the third would be derived from the two values, even when you tried to change the third. For an example, if you tried to edit the count TextInput field while price and amount exists, the count textfield would be switched to amount/price. By verifying that the field is not in focus before calculating its value, you avoid this – PhantomSpooks Jun 04 '21 at 11:08