React Native клик не на меню
Начал изучать React Native и появился вопрос. Делаю боковое меню три точки. Пробовал react-native-popup-menu, но оно тоже не закрывается, если кликать не в него.
import React, { useState } from 'react';
import { FlatList, View,} from 'react-native';
import { Title } from './Title';
export const MainScreen = () => {
const [mainTitle, setMainTitle] = useState([
{id: 1, title: 'test1' },
{ id: 2, title: 'test2' }
]);
return(
<View style={{flex:1}}>
<FlatList
keyExtractor={item => item.id.toString()}
data={mainTitle}
onEndReachedThreshold={0.7}
initialNumToRender={7}
renderItem={({item})=>
<Title title={item.title}/>
}
/>
</View>
);
};
и код Title
import React, { useState } from 'react';
import { StyleSheet, View, TouchableOpacity, Text, } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import {THEME} from '../theme';
export const Title = ({title}) => {
const [target, setTarget] = useState(false);
let menu;
if(target){
menu = (
<View style={styles.menu} >
<TouchableOpacity
style = {[styles.btn]}
onPress = {() => { console.log('Сохранить') }} >
<Text>Сохранить</Text>
</TouchableOpacity>
<TouchableOpacity
style = {styles.btn}
onPress = {() => { console.log('Удалить') }}
>
<Text>Удалить</Text>
</TouchableOpacity>
</View>
)
}else{
menu=null
}
return(
<>
<Text>{title}</Text>
<TouchableOpacity
style = {styles.button}
onPress = {() => {
setTarget(target? false : true)
}
}
>
<MaterialCommunityIcons name="dots-vertical" size={24} color={THEME.BLACK_COLOR} />
</TouchableOpacity>
{menu}
</>
);
};
const styles = StyleSheet.create({
menu:{
alignItems: 'center',
borderWidth: 2,
borderColor: THEME.COLOR,
},
btn:{
alignItems: 'center',
margin: 10,
height:'10%',
width: '20%',
},
button:{
width: '8%',
height: '75%',
height: 40,
width: 40,
marginTop:10,
}
});
когда открыто {menu} если клик будет не на {menu}, то {menu} должно закрываться. Не могу понять как клик не на {menu} поймать .
Ответы (1 шт):
Автор решения: MrYogurt
→ Ссылка
Как связать дочерний компонент с родителем:
const Parent = () => {
const handleClick = (event) => {
console.log("Clicked", event)
}
return (
<>
<Child handleClick={handleClick} /> // передаем обработчик дочернему компоненту
</>
)
}
const Child = (handleClick) => { // принимаем пропсом функцию в дочернем компоненте
return <Button onClick={(event) => handleClick(event)} /> // вызываем родительскую функцию и передаем ей ивент
}
По вашему коду все равно непонятно, как должно работать это меню, нужно заливать приложение на codepen и кидать ссылку. Но я на основе вашего кода описал, как вообще его можно создать:
import React, { useState } from 'react';
import { StyleSheet, View, TouchableOpacity, Text, } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { THEME } from '../theme';
import { FlatList, } from 'react-native';
import { Title } from './Title';
export const MainScreen = () => {
const [mainTitle, setMainTitle] = useState([
{ id: 1, title: 'test1' },
{ id: 2, title: 'test2' }
]);
return (
<View style={{ flex: 1 }}>
<FlatList
keyExtractor={item => item.id.toString()}
data={mainTitle}
onEndReachedThreshold={0.7}
initialNumToRender={7}
renderItem={({ item }) =>
<Title title={item.title} />
}
/>
</View>
);
};
export const Title = ({ title }) => {
const [target, setTarget] = useState(false);
return (
<>
<Text>{title}</Text>
<TouchableOpacity
style={styles.button}
onPress={() => setTarget(target ? false : true)}
>
<MaterialCommunityIcons name="dots-vertical" size={24} color={THEME.BLACK_COLOR} />
</TouchableOpacity>
{target && ( // заменил изначальный бред с записью в переменную, теперь меню будет отрисовано, когда таргет тру, так же можно использовать тернарное выражение
<View style={{ position: "absolute", width: "100%", height: "100%" }}> // делаем общий контейнер для меню и бэкграунда на весь экран в абсолюте, чтобы наложить поверх прочих элементов
<View style={styles.menu}> // здесь нужно прописать размерные стили для самого меню
<TouchableOpacity
style={[styles.btn]}
onPress={() => console.log('Сохранить')} >
<Text>Сохранить</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.btn}
onPress={() => console.log('Удалить')}
>
<Text>Удалить</Text>
</TouchableOpacity>
</View>
<View style={{ width: "100%", height: "100%" }}>
<TouchableOpacity style={{ width: "100%", height: "100%" }} onClick={() => setTarget(false)} /> // здесь растягиваем контейнер с обработчиком клика на весь экран и если все сделано правильно, контейнер будет находиться позади меню и при нажатии на пустое место за меню, будет происходить изменение стейта таргет на фолс
</View>
</View>
)}
</>
);
};
const styles = StyleSheet.create({
menu: {
alignItems: 'center',
borderWidth: 2,
borderColor: THEME.COLOR,
},
btn: {
alignItems: 'center',
margin: 10,
height: '10%',
width: '20%',
},
button: {
width: '8%',
height: '75%',
height: 40,
width: 40,
marginTop: 10,
}
});