S
S
ssdakj2020-05-17 04:55:25
React
ssdakj, 2020-05-17 04:55:25

How to pass the data received from the server to the edit form?

Hello everyone, how to send data from the server to the form for editing?
PS Perhaps after the product is received, it needs to be thrown somehow into the local state (fields), or there is another way without editing the fields in the store itself.

A piece of the reducer

const initialState = {
   product: {},
   loading: false,
   error: null
};

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


Product edit page:
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>
   );
};

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
paoluccio, 2020-05-18
@ssdakj

I think that relying on three points (a list of products, one product, and also a local state for the edited product) with identical data is extremely unnecessary, because Synchronization is messed up. I think that you need to rely only on the list of products from the redax and get the necessary data from it through selectors. For editing, you can use a temporary local state, which, if desired, can be reset and returned to the original data.
The names have been changed a bit to be more clear. But you, if anything, ask, I will try to help.

// 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) {
    // не удалось обновить продукт
  }
};

A
alex4answ, 2020-05-17
@alex4answ

1. Why store form data in a store (why is local state not good?)
2. Why would you use local state + a shared store ? (it seems like you need to select something 1 )
3. Why do you have a dependency on dispatch in useEffect ?
4. I don’t understand what your problem is, what specifically doesn’t work or doesn’t work?
everything is like this:

  1. in useEffect dispatcher "fetchProduct"
  2. in fetchProduct (action creator) dispatch "request sent" (for "loading" state)
  3. make an asynchronous request in the same place, and after its execution - dispatch "request accepted", put what you need in the store in the reducer.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question