我正在尝试创建一个简单的表单,它接受两个字符串,将它们存储在状态挂钩中,并清除自身 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>
从完整的应用程序中剥离出来,但仍然表现出有问题的行为
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, _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();
};
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;