Объяснение того, как и когда использовать React Native Higher Order Components
Меня часто спрашивают, когда использовать HOC (Компоненты высшего порядка) и когда использовать общие функции, которые обычно находятся в файлах со следующими именами:
- Helpers.js
- Commons.js
- Utils.js и так далее.
Я решил внести ясность в эту тему и объяснить, как и когда использовать каждый подход наиболее правильным образом. Так что просто следуйте.
Что такое компоненты высшего порядка React?
Компонент высшего порядка (HOC) – это функция, которая принимает компонент и возвращает компонент.
Конкретно компонент более высокого порядка — это функция, которая принимает компонент и возвращает новый компонент.
Какую проблему решает HOC?
Не будем шутить и зададим главный вопрос, какую проблему решают HOC? Зачем нам это нужно?
простой ответ: СУХОЙ, а что такое СУХОЙ, спросите вы? DRY — это принцип, который означает «Не повторяйся».
Я использовал принцип DRY на нескольких языках программирования в течение своей карьеры, и эксперты в отрасли всегда советовали мне это делать.
Например, вызовы API, сложные функции и многое другое.
Так что да, в некоторых случаях вы можете использовать функции Utils для этого, но HOC — это еще одна возможность сделать то же самое и даже больше. Вы можете совместно использовать общие функции, не повторяя один и тот же код, используя HOC.
Расширенный ответ заключается в том, что это нечто большее. Например, с помощью HOC мы можем добавить еще один компонент рядом с исходным компонентом и создать новый компонент, содержащий оба компонента.
Я объясню это следующим вопросом, а что, если мы хотим показать загрузчик при выборке данных по запросу API?
Из этого вопроса мы можем почувствовать силу HOC.
Учитесь на примере
Предположим, что у нас есть следующий компонент.
function ListOfUsers = ()=> { const [users, setUsers] = useState([]); const [isLoading, setIsLoading] = useState(false);useEffect(()=>{ ( async ()=>{ setIsLoading(true); const users = await axios.get(GET_USERS_URL.then(results => results); setUsers(users); setIsLoading(false); } )(); },[])render( <View> <Loader isLoading={isLoading}/> users.length ? users.map((user) => <UserCard user={user}/>) : <Text>No users</Text> </View> ) } export default ListOfUsers;
И теперь мы хотим реализовать подход HOC. Здесь мы можем заметить 2 вещи:
- Мы делаем запрос на вызов, чтобы получить всех пользователей с сервера.
- Мы используем компонент
Loader
.
В этом примере мы можем взять запрос API и компонент Loader
из компонента ListOfUsers
и переместить их в HOC, этот шаг сделает их повторно используемыми для каждого следующего вызова выборки.
Создание HOC
Теперь давайте создадим HOC. Допустимо вызывать HOC с префиксом with, как в нашем случае withAxiosRequest.
Файл можно создать в «./hoc/withAxiosRequest».
const withAxiosRequest = (OriginalComponent) => { return class extends React.Component { state = { isLoading: false}; createRequest = async (params: {url:string}) => { try { this.setState({ ...this.state, isLoading: true }); response = await axios.get(params.url).then((res) => res); this.setState({...this.state, isLoading: false}); return response; } catch (error) { this.setState({ ...this.state, isLoading: false }); return false; } } render() { return ( <> <Loader isLoading={this.state.isLoading} /> <OriginalComponent {...this.props} createRequest = {this.createRequest} /> </>) } } }export default withAxiosRequest;
HOC получает исходный компонент и отправляет обратно новый компонент с большей функциональностью.
Функциональность — это многократно используемая функция createRequest
. Теперь каждый раз, когда мы оборачиваем компонент withAxiosRequest
HOC, мы можем использовать функцию createRequest
.
Обернутый компонент теперь содержит компонент Loader
, поэтому любой вызов выборки с createRequest
автоматически активирует компонент Loader
.
Примечание. Этот пример позволяет вам только извлекать данные, вы можете улучшить эту концепцию HOC, чтобы поддерживать POST, DELETE, PUT и многое другое.
Последний шаг
Последний шаг — обернуть наш компонент ListOfUsers
withAxiosRequest
HOC.
function ListOfUsers = ({createRequest})=> { const [users, setUsers] = useState([]);useEffect(()=>{ ( async ()=>{ const users = await createRequest({url:GET_USERS_URL}); setUsers(users); } )(); },[])render( <View> users.length ? users.map((user) => <UserCard user={user}/>) : <Text>No users</Text> </View> ) } export default withAxiosRequest(ListOfUsers);
Как видите, мы можем получить функцию createRequest
в качестве реквизита в компоненте ListOfUsers
, поэтому нам больше не нужен запрос axios в компоненте ListOfUsers
.
Наш обернутый компонент теперь содержит компонент Loader
по умолчанию, поэтому нам больше не нужен компонент Loader
в компоненте ListOfUsers
.
Заключение
В этом примере мы увидели возможности HOC сделать наш код короче и пригодным для повторного использования с помощью функции createRequest
и включить компонент Loader
в каждый компонент, который мы выбрали для включения.
Компоненты высшего порядка делают ваш код более абстрактным, и как только вы освоитесь с ним, вы, возможно, будете использовать этот шаблон слишком часто.
Спасибо за то, что вы дочитали до сих пор, если вам нравится такой контент, и вы хотите поддержать меня как программиста и писателя, чтобы я писал больше статей, подобных этой, пожалуйста, подпишитесь подписаться на Medium (подписка на 5 долларов США в месяц) по моей ссылке, и вы получите неограниченный доступ ко всему на Medium.
Следите за новыми примерами и советами по React Native.
Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.