Как я могу установить значение initialState из бэкэнда для использования во входном значении формы? Входные данные не меняются после ввода значения = product.name из Бэкенда

#reactjs #react-redux #react-hooks #reducers #use-reducer

Вопрос:

Прямо сейчас я использую useEffect() , чтобы проверить наличие продукта через id параметр. И я могу установить initialState значение в пустую строку, но есть ли способ, которым мы можем установить initialState значение через серверную часть или после useEffect() того, как это будет сделано. Если я использую value={product.name} in <input/> , то значение есть в поле ввода, но оно никогда не меняется. Пожалуйста, Помогите.

   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]);
 

Устройство для изменения ввода

    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 amp;amp; (
    <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>
 

Ответ №1:

Я могу придумать два варианта при работе с асинхронными данными в сочетании с формой в вашей ситуации.

Первый вариант-загрузить компонент data перед отображением формы. Затем передайте данные в компонент формы как initialState . Недостатком этого решения является то, что форма полностью скрыта при загрузке данных.

Второй вариант-добавить в свой редуктор действие, которое обновляет более одного поля. Вы можете отправить это действие после загрузки данных о продукте и обновить все поля в соответствии с обновленными данными.

Вы можете упростить редуктор, добавив имя поля в полезную нагрузку.

 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]);
 

Комментарии:

1. Привет, Крис, Прежде всего, спасибо, что ответил мне. Вы помогли мне получить новую логику, так как в настоящее время я новичок в React. Пытаюсь сделать это сейчас. БОЛЬШОЕ СПАСИБО!