如何从后端设置 initialState 值以在表单输入值中使用?从后端给出 value = product.name 后输入没有改变
How can i set the initialState value from the backend to use in form input value? Input doesn't change after giving value = product.name from Backend
现在我正在使用 useEffect()
通过 id
参数检查产品。我可以将 initialState
值设置为空字符串,但是有什么方法可以通过后端或在 useEffect()
完成后设置 initialState
值。
如果我在 <input/>
中使用 value={product.name}
,那么该值就在输入字段中,但它永远不会改变。
请帮助。
const reducer = (state, { type, payload }) => {
switch (type) {
case "name":
return { ...state, name: { value: payload } };
case "desc":
return { ...state, desc: { value: payload } };
case "price":
return { ...state, price: { value: payload } };
case "img":
return { ...state, img: { value: payload } };
case "isFeatured":
return { ...state, isFeatured: { value: payload } };
default:
return { state };
}
};
const initialState = {
name: { value: "" },
desc: { value: "" },
price: { value: "" },
img: { value: "" },
isFeatured: { value: false },
};
产品组件
const [state, dispatch] = useReducer(reducer, initialState);
const [showForm, setShowForm] = useState(false); const [error, setError] = useState("Invalid"); const [product, setProduct] = useState(); const id = useParams().id; useEffect(() => {
const fetchHandler = async () => {
await fetch(`http://localhost:5000/products/${id}`)
.then(async (res) => await res.json())
.then((p) => setProduct(p.product))
.catch((err) => setError(err));
};
fetchHandler(); }, [id]);
InputChangeHandler
const inputChangeHandler = (e, name) => {
switch (name.toString()) {
case "name":
dispatch({ type: "name", payload: e.target.value });
break;
case "price":
dispatch({ type: "price", payload: e.target.value });
break;
case "desc":
dispatch({ type: "desc", payload: e.target.value });
break;
case "img":
dispatch({ type: "img", payload: e.target.value });
break;
case "isFeatured":
dispatch({ type: "isFeatured", payload: Boolean(e.target.checked) });
break;
default:
break;
}
};
我的表格
{showForm && (
<form onSubmit={submitForm}>
<FormControl>
<TextField
placeholder={product.name}
value={product.name}
onChange={(e) => inputChangeHandler(e, "name")}
margin="dense"
className="diff"
id="outlined-basic"
label="Name"
variant="outlined"
/>
<TextField
multiline
placeholder={product.description}
value={state.desc.value}
onChange={(e) => inputChangeHandler(e, "desc")}
id="outlined-basic"
margin="dense"
label="Description"
variant="outlined"
/>
<TextField
placeholder={product.price}
value={state.price.value}
onChange={(e) => inputChangeHandler(e, "price")}
margin="dense"
id="outlined-basic"
label="Price"
variant="outlined"
/>
<TextField
placeholder={product.image}
value={product.image}
onChange={(e) => inputChangeHandler(e, "img")}
margin="dense"
id="outlined-basic"
label="Image"
variant="outlined"
/>
<Checkbox
value={state.isFeatured.value}
onChange={(e) => inputChangeHandler(e, "isFeatured")}
name="checkedB"
color="primary"
/>
<Button type="submit"> Update</Button>
<FormHelperText id="my-helper-text">Update</FormHelperText>
</FormControl>
</form>
在您的情况下结合表单处理异步数据时,我可以想到两种选择。
第一个选项是在呈现表单组件之前加载data
。然后将数据作为 initialState
传递给表单组件。这种解决方案的缺点是在加载数据时表单完全隐藏。
第二个选项是向您的减速器添加一个更新多个字段的操作。您可以在加载产品数据后调度此操作,并根据更新的数据更新所有字段。
您可以通过将字段名称添加到有效负载来简化 reducer。
const reducer = (state, { type, payload }) => {
switch (type) {
case "change":
return { ...state, [payload.name]: { value: payload.value } };
case "productLoaded":
return { ...state, ...payload };
default:
return { state };
}
};
const inputChangeHandler = (e, name) => {
const value = e.target.type === 'checkbox' ? Boolean(e.target.checked) : e.target.value;
dispatch({ type: "change", payload: { name, value } });
};
useEffect(() => {
const fetchHandler = async () => {
await fetch(`http://localhost:5000/products/${id}`)
.then(async (res) => await res.json())
.then((p) => {
setProduct(p.product);
dispatch({ type: "productLoaded", payload: p.product });
})
.catch((err) => setError(err));
};
fetchHandler();
}, [id]);
现在我正在使用 useEffect()
通过 id
参数检查产品。我可以将 initialState
值设置为空字符串,但是有什么方法可以通过后端或在 useEffect()
完成后设置 initialState
值。
如果我在 <input/>
中使用 value={product.name}
,那么该值就在输入字段中,但它永远不会改变。
请帮助。
const reducer = (state, { type, payload }) => {
switch (type) {
case "name":
return { ...state, name: { value: payload } };
case "desc":
return { ...state, desc: { value: payload } };
case "price":
return { ...state, price: { value: payload } };
case "img":
return { ...state, img: { value: payload } };
case "isFeatured":
return { ...state, isFeatured: { value: payload } };
default:
return { state };
}
};
const initialState = {
name: { value: "" },
desc: { value: "" },
price: { value: "" },
img: { value: "" },
isFeatured: { value: false },
};
产品组件
const [state, dispatch] = useReducer(reducer, initialState);
const [showForm, setShowForm] = useState(false); const [error, setError] = useState("Invalid"); const [product, setProduct] = useState(); const id = useParams().id; useEffect(() => {
const fetchHandler = async () => {
await fetch(`http://localhost:5000/products/${id}`)
.then(async (res) => await res.json())
.then((p) => setProduct(p.product))
.catch((err) => setError(err));
};
fetchHandler(); }, [id]);
InputChangeHandler
const inputChangeHandler = (e, name) => {
switch (name.toString()) {
case "name":
dispatch({ type: "name", payload: e.target.value });
break;
case "price":
dispatch({ type: "price", payload: e.target.value });
break;
case "desc":
dispatch({ type: "desc", payload: e.target.value });
break;
case "img":
dispatch({ type: "img", payload: e.target.value });
break;
case "isFeatured":
dispatch({ type: "isFeatured", payload: Boolean(e.target.checked) });
break;
default:
break;
}
};
我的表格
{showForm && (
<form onSubmit={submitForm}>
<FormControl>
<TextField
placeholder={product.name}
value={product.name}
onChange={(e) => inputChangeHandler(e, "name")}
margin="dense"
className="diff"
id="outlined-basic"
label="Name"
variant="outlined"
/>
<TextField
multiline
placeholder={product.description}
value={state.desc.value}
onChange={(e) => inputChangeHandler(e, "desc")}
id="outlined-basic"
margin="dense"
label="Description"
variant="outlined"
/>
<TextField
placeholder={product.price}
value={state.price.value}
onChange={(e) => inputChangeHandler(e, "price")}
margin="dense"
id="outlined-basic"
label="Price"
variant="outlined"
/>
<TextField
placeholder={product.image}
value={product.image}
onChange={(e) => inputChangeHandler(e, "img")}
margin="dense"
id="outlined-basic"
label="Image"
variant="outlined"
/>
<Checkbox
value={state.isFeatured.value}
onChange={(e) => inputChangeHandler(e, "isFeatured")}
name="checkedB"
color="primary"
/>
<Button type="submit"> Update</Button>
<FormHelperText id="my-helper-text">Update</FormHelperText>
</FormControl>
</form>
在您的情况下结合表单处理异步数据时,我可以想到两种选择。
第一个选项是在呈现表单组件之前加载data
。然后将数据作为 initialState
传递给表单组件。这种解决方案的缺点是在加载数据时表单完全隐藏。
第二个选项是向您的减速器添加一个更新多个字段的操作。您可以在加载产品数据后调度此操作,并根据更新的数据更新所有字段。
您可以通过将字段名称添加到有效负载来简化 reducer。
const reducer = (state, { type, payload }) => {
switch (type) {
case "change":
return { ...state, [payload.name]: { value: payload.value } };
case "productLoaded":
return { ...state, ...payload };
default:
return { state };
}
};
const inputChangeHandler = (e, name) => {
const value = e.target.type === 'checkbox' ? Boolean(e.target.checked) : e.target.value;
dispatch({ type: "change", payload: { name, value } });
};
useEffect(() => {
const fetchHandler = async () => {
await fetch(`http://localhost:5000/products/${id}`)
.then(async (res) => await res.json())
.then((p) => {
setProduct(p.product);
dispatch({ type: "productLoaded", payload: p.product });
})
.catch((err) => setError(err));
};
fetchHandler();
}, [id]);