我正在尝试创建一个简单的表单,它接受两个字符串,将它们存储在状态挂钩中,并清除自身 onSubmit
,但似乎是通过输入的 onChange
更新状态挂钩(即 { {1}}) 具有清除刚刚输入的内容的效果,导致字段不可用。当这一行被移除时,输入保留了数据,但当然,它不再存储在状态钩子中。
我的理解是/是通过相应的 setter 方法更新状态挂钩不会产生副作用,尽管这里似乎并非如此。不过,在一个更简单的测试应用程序中,事情按预期工作。可以在 https://zzimm.com/ 和 https://zzimm.com/admin 处(在发布时)看到这种行为。
我认为相关的代码部分
钩子:
onChange={(t) => setUserSide(t.target.value)}
表格:
const [newWager,setWager] = useState(0);
const [userSide,setUserSide] = useState(0);
提交:
const Home = () => {
return(
<div classname="main">
<div classname="upper">
1: {retrievedSide1} : {potFor} WC<br/> 2: {retrievedSide2} : {potAgainst} WC
</div>
<div classname="card">
<form classname="form" id="submitWagerForm" autocomplete="off" onSubmit={wager}>
<label>
Enter your wager and side:
<br />
<input
classname="input"
type="text"
name="amount"
placeholder="# of WC"
onChange={(t) => setWager(t.target.value)}
/>
<input
classname="input"
type="text"
name="side"
placeholder="1 or 2"
onChange={(t) => setUserSide(t.target.value)}
/>
</label>
<button classname="button" type="submit" value="Submit">
Submit
</button>
</form>
App.js 的其余部分
从完整的应用程序中剥离出来,但仍然表现出有问题的行为
const wager = async (t) => {
t.preventDefault();
try{
const accounts = await window.ethereum.enable();
const account = accounts[0];
const _wager = web3.utils.toWei(newWager);
const gas = await eventWagerContract.methods.wager(userSide,_wager).estimateGas();
const post = await eventWagerContract.methods.wager(userSide,_wager).send({ from: account,gas });
getUserWager(t);
getcurrentPot(t);
}
catch(e)
{
alert('Apparently this is the best way to display blockchain errors :/\n\n' + e.message);
}
var form = document.getElementById("submitWagerForm");
form.reset();
};
更简单的测试应用
import logo from './logo.svg';
import React,{ useState } from "react";
import './App.css';
import { eventWager } from './abi/abi';
import { token } from './abi/abi';
import Web3 from "web3";
import { BrowserRouter as Router,Route,Switch } from 'react-router-dom';
const web3 = new Web3(Web3.givenProvider);
const contractAddress = "0x73A6Da02A8876C3E01017fB960C912dA0a423817";
const tokenAddress = "0x02F682030814F5AE7B1b3d69E8202d5870DF933f";
const eventWagerContract = new web3.eth.Contract(eventWager,contractAddress);
const tokenContract = new web3.eth.Contract(token,tokenAddress);
function App() {
// Getter hooks
const [retrievedWager,setRetrievedWager] = useState(0);
const [currentPot,setRetrievedCurrentPot] = useState(0);
const [potFor,setPotFor] = useState(0);
const [potAgainst,setPotAgainst] = useState(0);
const [retrievedUserSide,setRetrievedUserSide] = useState(0);
const [retrievedSide1,setRetrievedSide1] = useState("1");
const [retrievedSide2,setRetrievedSide2] = useState("2");
const [requestAddress,setRequestAddress] = useState(0);
const [requestAmount,setRequestAmount] = useState(0);
// Setter hooks
const [newWager,setWager] = useState(0);
const [userSide,setUserSide] = useState(0);
const [winningSide,setWinningSide] = useState(0);
// Getter methods
const getUserWager = async (t) => {
if(t) { t.preventDefault(); }
const accounts = await window.ethereum.enable();
const account = accounts[0];
const post = await eventWagerContract.methods.getWager(account).call();
const _wager = web3.utils.fromWei(post);
setRetrievedWager(_wager);
};
const getcurrentPot = async (t) => {
if(t) { t.preventDefault(); }
const post = await eventWagerContract.methods.getPot().call();
const _pot = web3.utils.fromWei(post);
setRetrievedCurrentPot(_pot);
};
// Setter methods
const wager = async (t) => {
t.preventDefault();
try{
const accounts = await window.ethereum.enable();
const account = accounts[0];
const _wager = web3.utils.toWei(newWager);
const gas = await eventWagerContract.methods.wager(userSide,gas });
getUserWager(t);
getcurrentPot(t);
}
catch(e)
{
alert('Apparently this is the best way to display blockchain errors :/\n\n' + e.message);
}
var form = document.getElementById("submitWagerForm");
form.reset();
};
const allowSpend = async (t) => {
t.preventDefault();
try{
const accounts = await window.ethereum.enable();
const account = accounts[0];
const gas = tokenContract.methods.approve(contractAddress,web3.utils.toWei('9999')).estimateGas();
const post = tokenContract.methods.approve(contractAddress,web3.utils.toWei('9999')).send({ from: account });
}
catch(e)
{
alert('Apparently this is the best way to display blockchain errors :/\n\n' + e.message);
}
};
const getcurrentSides = async (t) => {
if(t) { t.preventDefault(); }
const post = await eventWagerContract.methods.getSides().call();
// const post = await eventWagerContract.methods.getPot().call();
var substrings = post.split('||&&||');
setRetrievedSide1(substrings[0]);
setRetrievedSide2(substrings[1]);
};
const Home = () => {
return(
<div classname="main">
<div classname="upper">
1: {retrievedSide1} : {potFor} WC<br/> 2: {retrievedSide2} : {potAgainst} WC
</div>
<div classname="card">
<form classname="form" id="submitWagerForm" autocomplete="off" onSubmit={wager}>
<label>
Enter your wager and side:
<br />
<input
classname="input"
type="text"
name="amount"
placeholder="# of WC"
onChange={(t) => setWager(t.target.value)}
/>
<input
classname="input"
type="text"
name="side"
placeholder="1 or 2"
onChange={(t) => setUserSide(t.target.value)}
/>
</label>
<button classname="button" type="submit" value="Submit">
Submit
</button>
</form>
<br />
<div>
<button classname="button" onClick={getUserWager} type="button">
Your current wager:
</button>
{retrievedWager}
</div>
<br /> <br />
<div>
<button classname="button" onClick={getcurrentPot} type="button">
Click for current pot
</button>
{currentPot}
</div>
<br /><br />
<div>
<button classname="button" onClick={allowSpend} type="button">
Click to approve
</button>
</div>
<div classname="lower">
<form classname="form" onSubmit={getcurrentSides}>
<label>
<button classname="button" type="submit" value="Submit">
Get Sides
</button>
</label>
</form>
</div>
</div>
</div>
);
}
return (
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/admin">
{/* <Admin /> */}
</Route>
</Switch>
</Router>
);
}
export default App;