Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active May 17, 2025 13:24
Show Gist options
  • Save sunmeat/1426f6782180966fc21621360156e9ac to your computer and use it in GitHub Desktop.
Save sunmeat/1426f6782180966fc21621360156e9ac to your computer and use it in GitHub Desktop.
вариант взаимодействия с useContext
import { useState, createContext, useContext } from 'react';
import './css/FormContainer.css';
// создание контекста для формы
const FormContext = createContext(null);
// контекст тут нужен для упрощения взаимодействия между родительской формой и её дочерними инпутами
// вместо передачи данных и функций через props на каждый уровень, createContext и useContext позволяют проще делиться
// состоянием (formData) и функцией обновления (handleChange) напрямую
// это будет особенно полезно, когда в форме будет много полей
// контекст применяется внутри FormInput, чтобы получать и изменять соответствующие значения без лишней связи с родителем
// дочерняя компонента, использует контекст для доступа к данным формы
function FormInput({ label, type, name }) {
// получение данных и функции обновления из контекста
const { formData, handleChange } = useContext(FormContext);
// обработчик изменений, вызывает коллбэк handleChange из контекста
const handleInputChange = (e) => {
handleChange(name, e.target.value);
};
return (
<div className="form-group">
<label htmlFor={name}>{label}:</label>
<input
id={name}
type={type}
name={name}
value={formData[name]}
onChange={handleInputChange}
/>
</div>
);
}
// родительская компонента, управляет состоянием и предоставляет контекст
function FormContainer() {
// состояние формы
const [formData, setFormData] = useState({
name: '',
email: ''
});
// состояние для результата отправки
const [submitResult, setSubmitResult] = useState(null);
// коллбэк для обновления состояния формы
const handleChange = (field, value) => {
setFormData((prev) => ({
...prev,
[field]: value
}));
};
// коллбэк для обработки отправки формы
const handleSubmit = async (e) => {
e.preventDefault();
// сброс результата перед отправкой
setSubmitResult(null);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
const data = await response.json();
// логирование ответа API
console.log('ответ от API:', data);
setSubmitResult({ success: true, data });
} catch (error) {
// обработка ошибок API
console.error('ошибка API:', error);
setSubmitResult({ success: false, error: error.message });
}
};
// явное использование провайдера
// React возвращает объект контекста, у которого есть два ключевых компонента:
// 1) FormContext.Provider — компонент-провайдер
// 2) FormContext.Consumer — компонент-потребитель (реже используется)
// компонент <FormContext.Provider> сам по себе — обычный React-компонент, созданный внутри createContext
// он принимает специальный проп value, который доступен всем вложенным компонентам, использующим useContext(FormContext)
return (
<FormContext.Provider value={{ formData, handleChange }}>
<div className="form-container">
<h2>регистрационная форма</h2>
<form onSubmit={handleSubmit}>
<FormInput
label="имя"
type="text"
name="name"
/>
<FormInput
label="e-mail"
type="email"
name="email"
/>
<button type="submit">отправить</button>
</form>
<div className="form-data">
<h3>введённые данные:</h3>
<p>имя: {formData.name || '—'}</p>
<p>email: {formData.email || '—'}</p>
</div>
{submitResult && (
<div className="result">
{submitResult.success ? (
<>
<p className="success">успешно отправлено!</p>
<pre>{JSON.stringify(submitResult.data, null, 2)}</pre>
</>
) : (
<p className="error">
ошибка: {submitResult.error || 'не удалось отправить'}
</p>
)}
</div>
)}
</div>
</FormContext.Provider>
);
}
export default FormContainer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment