如何从后端设置 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]);