想要动态更新两个输入状态值,而不需要递归调用。

huangapple go评论74阅读模式
英文:

Want to update 2 input state values dynamically without recursive calls

问题

I am making a React application for a currency converter website. I have two <input> fields where the user can input the number to get the exchange rate as shown here:
Screenshot of Component

The <input> fields are as follows:

<>
  <input
    id="1"
    placeholder="0"
    type="number"
    value={state1.value}
    onChange={handleChange}
    disabled={loading}
  />

// rest of the component

  <input
    id="2"
    placeholder="0"
    type="number"
    value={state2.value}
    onChange={handleChange}
    disabled={loading}
  />

The states for the input fields are:

const [state1, setState1] = useState({
	value: '',
	currency: 'USD',
	src: 'https://hatscripts.github.io/circle-flags/flags/us.svg',
});
const [state2, setState2] = useState({
	value: '',
	currency: 'INR',
	src: 'https://hatscripts.github.io/circle-flags/flags/in.svg',
});

I want the state2 to be updated when the user types in state1. And vice-versa. I don't want the auto-update of state2 again changing state1. The state change should happen only when the user gives input.

I have tried using session state to avoid unnecessary API calls. It solves the problem except for the infinite recursion.

I have already written a useEffect for state1 which works as expected. Now I want to do the same for state2 without an infinite useEffect loop.

async function fetchCurrencyRate1(from, to) {
	setLoading(true);
	try {
		const response = await axios.get('http://localhost:4000/convert', {
			params: {
				from: from.currency,
				to: to.currency,
			},
		});
		setState2((state2) => ({
			...state2,
			value: (from.value * response.data.value).toFixed(4),
		}));
		console.log(response.data);
	} catch (error) {
		console.error(error);
	}
	setLoading(false);
}

useEffect(() => {
	setTimeout(() => {
		state1.value && fetchCurrencyRate1(state1, { ...state2 });
		if (state1.value === '') setState2({ ...state2, value: '' });
	}, 2000);
}, [state1]);
英文:

I am making a React application for a currency converter website. I have two &lt;input&gt; fields where the user can input the number to get the exchange rate as shown here:
Screenshot of Component

The &lt;input&gt; fields are as follows:

&lt;&gt;
  &lt;input
    id=&quot;1&quot;
    placeholder=&quot;0&quot;
    type=&quot;number&quot;
    value={state1.value}
    onChange={handleChange}
    disabled={loading}
  /&gt;

// rest of the component

  &lt;input
    id=&quot;2&quot;
    placeholder=&quot;0&quot;
    type=&quot;number&quot;
    value={state2.value}
    onChange={handleChange}
    disabled={loading}
  /&gt;

The states for the input fields are:

const [state1, setState1] = useState({
	value: &#39;&#39;,
	currency: &#39;USD&#39;,
	src: &#39;https://hatscripts.github.io/circle-flags/flags/us.svg&#39;,
});
const [state2, setState2] = useState({
	value: &#39;&#39;,
	currency: &#39;INR&#39;,
	src: &#39;https://hatscripts.github.io/circle-flags/flags/in.svg&#39;,
});

I want the state2 to be updated when the user types in state1. And vice-versa. I don't want the auto-update of state2 again changing state1. The state change should happen only when the user gives input.

I have tried using session state to avoid unnecessary API calls. It solves the problem except for the infinite recursion.

I have already written a useEffect for state1 which works as expected. Now I want to do the same for state2 without an infinite useEffect loop.

async function fetchCurrencyRate1(from, to) {
	setLoading(true);
	try {
		const response = await axios.get(&#39;http://localhost:4000/convert&#39;, {
			params: {
				from: from.currency,
				to: to.currency,
			},
		});
		setState2((state2) =&gt; ({
			...state2,
			value: (from.value * response.data.value).toFixed(4),
		}));
		console.log(response.data);
	} catch (error) {
		console.error(error);
	}
	setLoading(false);
}

useEffect(() =&gt; {
	setTimeout(() =&gt; {
		state1.value &amp;&amp; fetchCurrencyRate1(state1, { ...state2 });
		if (state1.value === &#39;&#39;) setState2({ ...state2, value: &#39;&#39; });
	}, 2000);
}, [state1]);

答案1

得分: 0

无限渲染发生是因为state1useEffect每次state1取新值时都会触发,由于在effect内部更新了state2,这会触发state2useEffect,而那里的代码会更新state1,然后state1useEffect将被无限调用,因为state1是一个对象,所以其值总是新的。

你不需要为此使用useEffect,而且你也不希望在每次输入更改时组件重渲染两次,你可以简单地为每个输入创建两个单独的handleChange函数,并在其中的每一个中进行逻辑处理,类似于这样:

const handleChangeOne = async (e) => {
  // 在这里你可以获取数据
  setState1((prev) => {
    return {
      ...prev,
      value: e.target.value,
    };
  });
  setState2((prev) => {
    return {
      ...prev,
      value: (from.value * response.data.value).toFixed(4), 
    };
  });
};

const handleChangeTwo = async (e) => {
  // 获取数据
  setState2((prev) => {
    return {
      ...prev,
      value: Number(e.target.value),
    };
  });
  setState1((prev) => {
    //
    return {
      ...prev,
      value: (from.value * response.data.value).toFixed(4),
    };
  });
};

希望这可以帮助你解决问题。

英文:

The infinite render occurs because the useEffect of state1 will fire each time state1 take a new value and since inside the effect you update state2 and this triggers useEffect of state2 and the code there updates state1 then useEffect of state1 will be called infinitely because state1 is an object so its value is always new.

you don't need useEffect for that, also you don't want to rerender the component twice on each input change you can simply make two separate handleChange functions for each input and make your logic in each one of them <br>something like this:

const handleChangeOne = async (e) =&gt; {
  // you can fetch data here instead
  setState1((prev) =&gt; {
    return {
      ...prev,
      value: e.target.value,
    };
  });
  setState2((prev) =&gt; {
    return {
      ...prev,
      value: (from.value * response.data.value).toFixed(4), 
    };
  });
};
const handleChangeTwo = async (e) =&gt; {
  // fetch data
  setState2((prev) =&gt; {
    return {
      ...prev,
      value: Number(e.target.value),
    };
  });
  setState1((prev) =&gt; {
    //
    return {
      ...prev,
      value: (from.value * response.data.value).toFixed(4),
    };
  });
};

huangapple
  • 本文由 发表于 2023年7月13日 13:23:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定