javascriptreact-nativereact-native-tools

How to update other fields based on a field value in forms of React Native?


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


Solution

  • 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