Использование рендеринга в React становится очень часто используемым шаблоном, и на то есть веские причины.
Мы собираемся использовать пакет перекомпоновать, который, вероятно, известен большинству разработчиков React благодаря своему набору удобных компонентов более высокого порядка. Для тех, кто этого не делает, он позволяет, например, использовать withState
HOC для обертывания компонента без состояния, чтобы фактически иметь состояние. Я рекомендую проверить документацию для получения дополнительной информации.
Давайте погрузимся в код
Предполагая, что у вас запущено приложение React, все, что вам нужно сделать, это: yarn add recompose
и все готово.
Государственный провайдер
Это очень простая реализация вспомогательного компонента, который предоставляет вам 2 значения; state
и setState.
Полный StateProvider.js выглядит следующим образом:
import { withState } from ‘recompose’ const StateProvider = withState( ‘state’, ‘setState’, props => props.initialState )(({ children, state, setState }) => children(state, setState)) export default StateProvider
Это все. Обратите внимание, что здесь нет кода React. То, что мы делаем, - это использование компонента перекомпоновки withState
более высокого порядка, чтобы обернуть функцию, которая передает 2 основных параметра (состояние и setState) в children
и возвращает его.
Теперь мы можем использовать это так:
<StateProvider initialState={1}> {(counter, setCounter) => ( <Fragment> <h2>{counter}</h2> <button onClick={() => setCounter(counter + 1}> Increment </button> </Fragment> )} </StateProvider>
Поскольку setState
и state
- это просто переданные параметры, мы можем назвать их по своему усмотрению, в данном случае это counter
и setCounter
. Однако initialState
нужно называть так же, поскольку это опора.
initialState
может иметь любое значение, которое вы поместили в обычный this.state
, обычно это объект, но также массив или примитивное значение.
Переключать
Мы также можем создать что-то подобное, например, многоразовый компонент Toggle:
import { withStateHandlers } from 'recompose' export default withStateHandlers( ({ initial }) => ({ isToggled: !!initial }), { toggle: ({ isToggled }) => () => ({ isToggled: !isToggled }) } )(({ children, isToggled, toggle }) => children(isToggled, toggle))
Что можно использовать следующим образом:
<Toggle initial={false}> {(isOn, toggle) => ( <Fragment> <input type="checkbox" checked={isOn} onClick={toggle} /> {isOn && <p>Show when checked ^</p>} </Fragment> )} </Toggle>
Форма (он же Formik wannabe)
Компонент формы, имеющий API-интерфейс, аналогичный классной библиотеке Formik, хотя эта реализация намного проще.
export const Form = withStateHandlers( ({ initialValues }) => ({ values: initialValues }), { handleChange: ({ values }) => e => ({ values: { ...values, [e.target.name]: e.target.value } }), handleSubmit: ({ values }, { onSubmit }) => () => { onSubmit(values) // call onSubmit prop with values return { values: {} } // clear form } } )(({ children, values, handleChange, handleSubmit }) => children(values, handleChange, handleSubmit) )
Использование:
<Form initialValues={{ firstName: 'John', lastName: 'Doe' }} onSubmit={values => console.log(values)} > {(values, handleChange, handleSubmit) => ( <div> <input name="firstName" onChange={handleChange} value={values.firstName} /> <input name="lastName" onChange={handleChange} value={values.lastName} /> <button type="submit" onClick={handleSubmit}> Submit </button> </div> )} </Form>
Перед закрытием
Приведенный выше код предназначен только для демонстрации того, насколько просто создать свои собственные вспомогательные компоненты, использующие шаблон опоры рендеринга. Могут быть ошибки, и в большинстве случаев он слишком упрощен, чтобы его можно было легко понять.
И спасибо, что нашли время прочитать мою первую статью!