Хуки (hooks) — это специальные функции, которые позволяют вам использовать состояние и другие возможности React в функциональных компонентах. React Native поддерживает все основные хуки React. В этой статье мы подробно рассмотрим основные хуки и предоставим примеры для каждого из них.
useState
Хук useState
позволяет вам добавлять состояние в функциональные компоненты.
Пример:
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Text style={styles.text}>Count: {count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 24,
},
});
export default Counter;
useEffect
Хук useEffect
позволяет выполнять побочные эффекты в функциональных компонентах, такие как загрузка данных, установка подписок и изменение DOM.
Пример:
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
const DataFetcher = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return (
<View style={styles.container}>
<Text style={styles.text}>{data ? JSON.stringify(data) : 'Loading...'}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 18,
},
});
export default DataFetcher;
useContext
Хук useContext
позволяет вам использовать контекст в функциональных компонентах.
Пример:
import React, { useContext, createContext } from 'react';
import { View, Text, StyleSheet } from 'react-native';
const MyContext = createContext();
const Display = () => {
const value = useContext(MyContext);
return <Text style={styles.text}>Value: {value}</Text>;
};
const App = () => {
return (
<MyContext.Provider value="Hello from Context!">
<View style={styles.container}>
<Display />
</View>
</MyContext.Provider>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 18,
},
});
export default App;
useReducer
Хук useReducer
позволяет вам управлять сложным состоянием в функциональных компонентах с использованием редюсера.
Пример:
import React, { useReducer } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const initialState = { count: 0 };
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};
const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<View style={styles.container}>
<Text style={styles.text}>Count: {state.count}</Text>
<Button title="Increment" onPress={() => dispatch({ type: 'increment' })} />
<Button title="Decrement" onPress={() => dispatch({ type: 'decrement' })} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 24,
},
});
export default Counter;
useRef
Хук useRef
позволяет вам создавать мутируемые ссылки, которые сохраняются между рендерингами компонента.
Пример:
import React, { useRef } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const FocusableInput = () => {
const inputRef = useRef(null);
return (
<View style={styles.container}>
<input ref={inputRef} style={styles.input} />
<Button title="Focus Input" onPress={() => inputRef.current.focus()} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
input: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
paddingLeft: 10,
width: '80%',
},
});
export default FocusableInput;
useMemo
Хук useMemo
позволяет вам мемоизировать вычисления и кэшировать результаты между рендерингами.
Пример:
import React, { useMemo, useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const ExpensiveComponent = ({ count }) => {
const expensiveCalculation = (num) => {
console.log('Calculating...');
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
return <Text style={styles.text}>Calculated Value: {memoizedValue}</Text>;
};
const App = () => {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Button title="Increment" onPress={() => setCount(count + 1)} />
<ExpensiveComponent count={count} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 18,
},
});
export default App;
useCallback
Хук useCallback
позволяет мемоизировать функции, чтобы предотвратить их пересоздание между рендерингами.
Пример:
import React, { useCallback, useState } from 'react';
import { View, Button, Text, StyleSheet } from 'react-native';
const ChildComponent = React.memo(({ onClick }) => {
console.log('ChildComponent re-rendered');
return <Button title="Click me" onPress={onClick} />;
});
const App = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<View style={styles.container}>
<Text style={styles.text}>Count: {count}</Text>
<ChildComponent onClick={increment} />
</View>
);
};
const styles =
StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 24,
},
});
export default App;
useLayoutEffect
Хук useLayoutEffect
работает так же, как useEffect
, но запускается синхронно после всех изменений DOM.
Пример:
import React, { useLayoutEffect, useRef } from 'react';
import { View, Text, StyleSheet } from 'react-native';
const LayoutEffectExample = () => {
const ref = useRef(null);
useLayoutEffect(() => {
console.log(ref.current.getBoundingClientRect());
}, []);
return (
<View style={styles.container}>
<Text ref={ref} style={styles.text}>Hello, World!</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 24,
},
});
export default LayoutEffectExample;
useImperativeHandle
Хук useImperativeHandle
позволяет вам настраивать экземпляр, который передается родительским компонентам с использованием ref
.
Пример:
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
import { View, Button, Text, StyleSheet } from 'react-native';
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} style={styles.input} />;
});
const App = () => {
const customInputRef = useRef();
return (
<View style={styles.container}>
<CustomInput ref={customInputRef} />
<Button title="Focus the input" onPress={() => customInputRef.current.focus()} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
input: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
paddingLeft: 10,
width: '80%',
},
});
export default App;
useDebugValue
Хук useDebugValue
позволяет отображать метки для хуков в React DevTools.
Пример:
import React, { useState, useEffect, useDebugValue } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const useOnlineStatus = () => {
const [isOnline, setIsOnline] = useState(false);
useEffect(() => {
const handleOnline = () => setIsOnline(true);
const handleOffline = () => setIsOnline(false);
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline;
};
const App = () => {
const isOnline = useOnlineStatus();
return (
<View style={styles.container}>
<Text style={styles.text}>You are currently: {isOnline ? 'Online' : 'Offline'}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 18,
},
});
export default App;
Заключение
Хуки в React и React Native предоставляют мощные возможности для управления состоянием, выполнением побочных эффектов и другими задачами в функциональных компонентах. В этой статье мы рассмотрели основные хуки и привели примеры их использования. Надеемся, что эти примеры помогут вам лучше понять, как использовать хуки в ваших проектах.