← Назад к вопросам
Как прокидываешь состояние по дочерним компонентам?
2.0 Middle🔥 191 комментариев
#React
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы передачи состояния дочерним компонентам
В React существует несколько паттернов для передачи состояния и данных вниз по иерархии компонентов. Выбор метода зависит от сложности приложения и структуры компонентов.
Props Drilling (Прямая передача через props)
Самый простой способ - передача данных через props на каждом уровне:
function Parent() {
const [user, setUser] = useState({ name: 'John', age: 30 });
return (
<div>
<Level1 user={user} setUser={setUser} />
</div>
);
}
function Level1({ user, setUser }) {
return (
<div>
<Level2 user={user} setUser={setUser} />
</div>
);
}
function Level2({ user, setUser }) {
return (
<div>
<Level3 user={user} setUser={setUser} />
</div>
);
}
function Level3({ user, setUser }) {
return (
<div>
<p>Name: {user.name}</p>
<button onClick={() => setUser({ ...user, name: 'Jane' })}>
Change Name
</button>
</div>
);
}
Context API (Более оптимально для глубокой иерархии)
Когда компонентов много, Context API избавляет от prop drilling:
const UserContext = React.createContext();
export function UserProvider({ children }) {
const [user, setUser] = useState({ name: 'John', age: 30 });
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
}
export function useUser() {
const context = useContext(UserContext);
if (!context) {
throw new Error('useUser must be used within UserProvider');
}
return context;
}
function DeepComponent() {
const { user, setUser } = useUser();
return (
<div>
<p>Name: {user.name}</p>
<button onClick={() => setUser({ ...user, name: 'Jane' })}>
Change Name
</button>
</div>
);
}
function App() {
return (
<UserProvider>
<Level1 />
</UserProvider>
);
}
useState + useCallback для оптимизации
Чтобы избежать лишних перерендеров при передаче обработчиков:
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prev => prev + 1);
}, []);
const decrement = useCallback(() => {
setCount(prev => prev - 1);
}, []);
return (
<div>
<Counter
count={count}
onIncrement={increment}
onDecrement={decrement}
/>
<ChildComponent count={count} />
</div>
);
}
function Counter({ count, onIncrement, onDecrement }) {
return (
<div>
<p>Count: {count}</p>
<button onClick={onIncrement}>+</button>
<button onClick={onDecrement}>-</button>
</div>
);
}
Compound Components Pattern
Паттерн для создания связанных компонентов с общим состоянием:
function Form() {
const [formData, setFormData] = useState({
name: '',
email: ''
});
return (
<FormProvider value={{ formData, setFormData }}>
<FormName />
<FormEmail />
<FormSubmit />
</FormProvider>
);
}
function FormName() {
const { formData, setFormData } = useFormContext();
return (
<input
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Name"
/>
);
}
function FormEmail() {
const { formData, setFormData } = useFormContext();
return (
<input
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
placeholder="Email"
/>
);
}