@ssdakj

Как прокинуть данные полученные с сервера в форму редактирования?

Всем привет, как прокинуть данные с сервера в форму для редактирования ?
P.S. Возможно после того как продукт получен, его нужно прокинуть как-то в локальный стейт (fields), или есть другой способ не редактируя поля в самом store

Кусок редьюсера
const initialState = {
   product: {},
   loading: false,
   error: null
};

export default (state = initialState, action) => {
   switch(action.type) {
      case 'FETCH_PRODUCT_REQUEST':
         return { ...state, loading: true }
      ...
   }
}
...


Страница редактирования продукта:
const ProductEdit = () => {
   const params = useParams();
   const dispatch = useDispatch();
   const [fields, setFields] = useState({
      name: '',
      text: '',
      price: null
   });
   const { product } = useSelector(state => state.products);

   useEffect(() => {
      dispatch(fetchProduct(params.id));
   }, [dispatch, params.id]);

   const onChange = ({ target: { name, value } }) => {
      setFields(fields => ({ ...fields, [name]: value }));
   };

   const onSubmit = () => { ... };

   return (
      <form onSubmit={onSubmit}>
         <input type='text' name='name' value={fields.name} onChange={onChange} />
         <input type='text' name='text' value={fields.text} onChange={onChange} />
         <input type='text' name='price' value={fields.price} onChange={onChange} />
         <button>update product</button>
      </form>
   );
};
  • Вопрос задан
  • 292 просмотра
Решения вопроса 1
@paoluccio
Думаю, что опираться на три точки(список продуктов, один продукт, еще и локальный стейт для редактируемого продукта) с идентичными данными крайне излишне, т.к. создаётся путаница с синхронизацией. Считаю, что нужно опираться только на список продуктов из редакса и доставать из него нужные данные через селекторы. Для редактирования можно использовать временный локальный стейт, который при желании можно сбросить и вернуться к исходным данным.

Имена немного изменил, чтобы было более понятно. Но вы, если что, спрашивайте, постараюсь помочь.

// Component
const ProductEdit = () => {
  const [editableData, setEditableData] = useState({});

  const { id } = useParams();
  // пытаемся достать продукт по id из списка
  const selectedProduct = useSelector(state => (
    state.products.find(product => product.id === id)
  ));

  useEffect(() => {
    // если продукт был найден, сразу заносим его в локальный стейт
    if (selectedProduct) {
      setEditableData(selectedProduct);
    }
    // иначе получаем данные с бэкэнда(минуя редакс) и затем заносим в локальный стейт
    // этот кейс будет срабатывать в случае если страница была перезагружена
    else {
      API.fetchProductById(id).then(fetchedProduct => setEditableData(fetchedProduct));
    }
  }, [selectedProduct, id]);

  const onChange = ({ target: { name, value } }) => {
    setEditableData(currentData => ({ ...currentData, [name]: value }));
  };

  const dispatch = useDispatch();
  const onSubmit = e => {
    e.preventDefault();
    dispatch(updateProduct({ id, ...editableData }));
  };

  return (
    <form onSubmit={onSubmit}>
      <input type='text' name='name' value={editableData.name || ''} onChange={onChange} />
      <input type='text' name='text' value={editableData.text || ''} onChange={onChange} />
      <input type='text' name='price' value={editableData.price || ''} onChange={onChange} />
      <button>update product</button>
    </form>
  );
};

// Thunk
const updateProduct = product => async (dispatch, getState) => {
  try {
    await API.updateProduct(product);
    // проверяем на наличие списка продуктов, может не быть если страница перезагружалась
    if (getState().products.length) {
      dispatch(mergeUpdatedProduct(product));
      // ловим type этого экшна в редьюсере и перезаписываем старый продукт в списке
    }
    // если же список пустой, то при возврате на страницу показа продуктов заново получаем все данные
    // к тому моменту обновлённый продукт уже успешно будет проживать в бд
  } catch (error) {
    // не удалось обновить продукт
  }
};
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
alex4answ
@alex4answ
1. Зачем хранить данные формы в store ( чем локальное состояние не подходит? )
2. Зачем вы используйте локальное состояние + общий store ? ( вроде как нужно выбрать что-то 1 )
3. Зачем у вас в useEffect зависимость от dispatch ?

4. Я не понял в чем у вас проблема, что конкретно не работает или не получается?
все примерно так:
  1. в useEffect диспатчите "fetchProduct"
  2. в fetchProduct (action creator) диспатчите "запрос отправлен" (для состояния "загрузка" )
  3. там же делайте асинхронный запрос, и по его выполнению - диспатчите "запрос принят", в редьюсере кладете в store что вам нужно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы