我有一个简单的Expense Tracker,它带有一个将事务添加到mongoDB后端的表单。我正在使用上下文API和材料UI表单子组件。我一辈子都无法弄清楚如何在onSubmit被触发后清除文本字段,但是总体来说我对React和Javascript还是很陌生。我还看过其他一些有关创建函数以使用按钮触发onClick的文章,但是由于我的全局上下文中有一个“ initialState”,因此我不确定这是正确的方法。我还看到了其他使用appReducer进行此操作的路线,但我不知道如何应用它。为了清楚起见,我希望它清除onSubmit表单,而不是单击“清除字段”的按钮。下面是我的代码:
表单组件
type name value TTL
CNAME www @ 1 hour
全球状态
import React, { useState, useContext } from "react";
import { GlobalContext } from "../context/GlobalState";
// UI for Text Field
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import Grid from "@material-ui/core/Grid";
// UI and utils for date picker
import "date-fns";
import DateFnsUtils from "@date-io/date-fns";
import {
MuiPickersUtilsProvider,
KeyboardDatePicker
} from "@material-ui/pickers";
const useStyles = makeStyles(theme => ({
root: {
"& > *": {
align: "center",
margin: theme.spacing(1),
width: 200,
flexgrow: 1
}
},
textfield: {
height: 38
},
button: {
height: 38,
align: "center"
},
grid: {
fullwidth: true,
direction: "row",
justify: "center",
alignItems: "center",
display: "flex",
flexDirection: "column",
justifyContent: "center"
}
}));
export const AddTransaction = () => {
const classes = useStyles();
const [transactionDate, setTransactionDate] = useState(new Date());
const [text, setText] = useState('');
const [amount, setAmount] = useState(0);
const { addTransaction } = useContext(GlobalContext);
const onSubmit = e => {
e.preventDefault();
const newTransaction = {
transactionDate,
text,
amount: +amount
};
addTransaction(newTransaction);
};
return (
<React.Fragment>
<h3 align="center">Add new transaction</h3>
<Grid container className={classes.grid}>
<form
className={classes.root}
noValidate
autoComplete="off"
onSubmit={onSubmit}
>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
disableToolbar
variant="inline"
format="MM/dd/yyyy"
margin="normal"
id="Transaction Date"
label="Transaction Date"
onChange={e => setTransactionDate(e)}
value={transactionDate}
KeyboardButtonProps={{
"aria-label": "change date"
}}
/>
</MuiPickersUtilsProvider>
<TextField
className={classes.textfield}
id="Transaction Name"
label="Transaction Name"
variant="outlined"
size="small"
type="text"
margin="dense"
onChange={e => setText(e.target.value)}
value={text}
required = {true}
/>
<TextField
className={classes.textfield}
id="Amount"
label="Amount"
variant="outlined"
size="small"
type="number"
margin="dense"
onChange={e => setAmount(e.target.value)}
value={amount}
required = {true}
/>
<Button
className={classes.button}
variant="contained"
color="primary"
type="submit"
fullwidth
>
Add transaction
</Button>
</form>
</Grid>
</React.Fragment>
);
};
App Reducer
import React, { createContext, useReducer } from 'react';
import AppReducer from './AppReducer';
import axios from 'axios';
// Initial state
const initialState = {
transactions: [],
error: null,
loading: true
}
// Create context
export const GlobalContext = createContext(initialState);
// Provider component
export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(AppReducer, initialState);
// Actions
async function getTransactions() {
try {
const res = await axios.get('/api/v1/transactions');
dispatch({
type: 'GET_TRANSACTIONS',
payload: res.data.data
});
} catch (err) {
dispatch({
type: 'TRANSACTION_ERROR',
payload: err.response.data.error
});
}
}
async function deleteTransaction(id) {
try {
await axios.delete(`/api/v1/transactions/${id}`);
dispatch({
type: 'DELETE_TRANSACTION',
payload: id
});
} catch (err) {
dispatch({
type: 'TRANSACTION_ERROR',
payload: err.response.data.error
});
}
}
async function addTransaction(transaction) {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
try {
const res = await axios.post('/api/v1/transactions', transaction, config);
dispatch({
type: 'ADD_TRANSACTION',
payload: res.data.data
});
} catch (err) {
dispatch({
type: 'TRANSACTION_ERROR',
payload: err.response.data.error
});
}
}
return (<GlobalContext.Provider value={{
transactions: state.transactions,
error: state.error,
loading: state.loading,
getTransactions,
deleteTransaction,
addTransaction
}}>
{children}
</GlobalContext.Provider>);
}
答案 0 :(得分:1)
我终于能够在哥哥的帮助下解决这个问题。他建议将表单的私有状态与我的全球状态分开管理是不理想的,但这已经完成了工作。我在addTransaction调用之后重置了表单状态。
表单组件
//No changes to import or styling //
export const AddTransaction = () => {
const classes = useStyles();
const [transactionDate, setTransactionDate] = useState(new Date());
const [text, setText] = useState('');
const [amount, setAmount] = useState(0);
const { addTransaction } = useContext(GlobalContext);
const onSubmit = e => {
e.preventDefault();
const newTransaction = {
transactionDate,
text,
amount: +amount
};
addTransaction(newTransaction);
// Here is what I've added that will return the form to it's original state
setText('') //this resets the textfield to an empty string
setAmount(0) //same as above but 0 amount
};
//no changes to return//
答案 1 :(得分:0)
您好,谢谢您提出问题。
我要解决此问题的方法是对输入字段使用usestate挂钩,然后使用onCLick将其设置为零。 这是一个示例:
假设我的网站上有一个名为search的输入字段,该输入字段已与google搜索连接。这意味着我网站上的搜索栏会调用google上的搜索栏。一旦用户输入了一个值并单击了搜索,我就会将setSearch()调用为用户输入的新值。
const [search, setSearch] = useState(""); // for user input
//once the user inputs a value and clicks a button I will call **two functions**
//The first fires off a google search
const searchRequest = () => {
window.open(`https://www.google.com/search?q=${search}`, `_blank`);
};
// the second function does what you want, it sets the value of search to an empty string.
<Button variant="outlined" size="large"
onClick={(e) => {
searchRequest(e);
setSearch(" ")}} // <-- I think this solves your problem, if you follow my logic.
>
Search
</Button>
希望这会有所帮助,如果需要进一步说明,请告诉我。