#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. Пытаюсь сделать это сейчас. БОЛЬШОЕ СПАСИБО!