I have a tree chart in which each node has children nodes. when clicking on a node a drawer opens exactly like a modal. But the problem is that it rerenders based on number of children available on screen like 6 or 5 times. When I click on node it sets this setIsOpen(true) so I think it's it sets this for all nodes that's why it renders more than 1 time. I saw that in inspect. I tried to use use callback and memo but it didn't work.
const Root = (): JSX.Element => {
return (
<div className={styles.card}>
<Flex style={{ marginTop: 25, gap: 8 }} flexCol itemsCenter justifyCenter>
<OrgIcon />
<Text typography="title" weight="bold" color="rgba(6, 6, 43, 0.6)">
Jisr HR
</Text>
</Flex>
</div>
);
};
type ChartProps = {
onSubmit: (vals: any) => void
};
const Chart = (props: ChartProps): JSX.Element => {
const { onSubmit } = props;
return (
<Tree
lineHeight="50px"
lineWidth="1px"
lineColor="rgb(8 15 54 / 24%);"
lineBorderRadius="30px"
label={<Root />}
>
{data.map((d, i) => (
<Node data={d} key={i} onSubmit={onSubmit} />
))}
</Tree>
);
};
export default Chart;
const Node = ({ data, onSubmit }: Props): JSX.Element => {
const [show, setShow] = useState(false);
const [showEmployeeList, setShowEmployeeList] = useState(false);
const count = data.child?.length || 0;
const { setIsOpen, setIsEdit } = useDepartment();
return (
<>
<TreeNode
key={data.name}
label={
<Card
onClick={(): void => setIsOpen(true)}
onClickEmp={(): void => setShowEmployeeList(true)}
onClickEdit={(): void => { setIsOpen(true); setIsEdit(true); }}
name={data.name}
collapse={
<div
className={styles.collapse}
onClick={(): void => setShow(!show)}
>
<Text typography="paragraph14" color="#475467">
{count}
</Text>
<FAICon
icon={`fa-regular ${show ? 'fa-angle-down' : 'fa-angle-up'}`}
color={undefined}
fontSize={undefined}
/>
</div>
}
/>
}
>
{show
? data.child &&
data.child.map((d: any, i: number): JSX.Element =>
<Node data={d} key={i} onSubmit={onSubmit} />)
: null}
</TreeNode>
<AddDepartmentForm
onSubmit={onSubmit}
/>
<DepartmentEmployees
showEmployeeList={showEmployeeList}
setShowEmployeeList={setShowEmployeeList}
/>
</>
);
};
export default Node;
const Card = ({
name,
collapse,
onClick,
onClickEmp,
onClickEdit,
}: ListData): JSX.Element => {
return (
<div
className={styles.card}
>
<div
className={styles.boxUp}
onClick={onClick}
>
<PlusIcon className={styles.hoverPlus} />
</div>
<div
className={styles.card_header}
onClick={onClickEdit}
>
<Flex itemsCenter style={{ gap: 15 }}>
<DepartmentIcon />
<Text typography="paragraph16" color="rgba(6, 6, 43, 0.6)">
{name}
</Text>
</Flex>
</div>
<div style={{ margin: '12px 10px 12px 10px' }}>
<Flex style={{ gap: 8 }} itemsCenter>
<PlusIcon className={styles.plusIcon} />
<Text typography="paragraph16" color="#2353f5">
Assign Manager
</Text>
</Flex>
<Spacer height={10} />
<Flex justifyBetween>
<Badge
label={
<Flex style={{ gap: 7 }}>
<EmployeeIcon />
23
</Flex>
}
size="large"
type="gray"
variant="stroke"
onClick={onClickEmp}
/>
{collapse}
</Flex>
</div>
<div className={styles.boxDown}>
<PlusIcon className={styles.hoverPlus} />
</div>
</div>
);
};
export default Card;
Related
When I delete products from my cart, the last product <CartComponent /> which I want to delete doesn't animate. I use framer-motion to this project and next.js/chakra-ui/redux.
I followed the docs on framer motion with animate-presence:
Multiple children AnimatePresence works the same way with multiple
children. Just ensure that each has a unique key and components will
animate in and out as they're added or removed from the tree.
I recorded a video on youtube to show the problem more clearly:
youtube video showing the problem
Here's cart page below:
// some imports up here :D /\
const MotionBox = motion<BoxProps>(Box);
const Cart = () => {
const selectProducts = useSelector(selectAllDataFromStore);
const dispatch = useDispatch();
return (
<>
<PageLayout title='Koszyk' description='Fake Sugar - koszyk'>
<VStack>
{selectProducts.length > 0 ? (
<Box>
<AnimatePresence>
{selectProducts.map((item) => {
return (
<MotionBox
animate={{ opacity: 1 }}
exit={{ opacity: 0, x: -200 }}
key={item.slug}
>
<CartComponent item={item} />
</MotionBox>
);
})}
</AnimatePresence>
<Box pt={4}>
<Center>
<Divider orientation='horizontal' />
</Center>
<Button mt={2} onClick={() => dispatch(clearCart())}>
Wyczyść koszyk
</Button>
</Box>
</Box>
) : (
<MotionBox
initial={{ opacity: 0, y: -400 }}
animate={{ opacity: 1, y: 0, transition: { duration: 2 } }}
zIndex='tooltip'
>
<Flex direction='column' align='center' justify='center'>
<Heading as='h3' fontSize='3xl'>
Twój koszyk jest pusty.
</Heading>
<NextLink href='/' passHref>
<Button colorScheme='gray'>Przeglądaj produkty</Button>
</NextLink>
</Flex>
</MotionBox>
)}
</VStack>
</PageLayout>
</>
);
};
export default Cart;
edit 1: I didnt mention that before I wrap it with ternary operator, it was animating the last component when I delete it. So everything was good!
so it was like
youtube video: before it worked it was like
const Cart = () => {
const selectProducts = useSelector(selectAllDataFromStore);
const dispatch = useDispatch();
return (
<>
<PageLayout title='Koszyk' description='Fake Sugar - koszyk'>
<VStack>
<Box>
<AnimatePresence>
{selectProducts.map((item) => {
return (
<MotionBox
animate={{ opacity: 1 }}
exit={{ opacity: 0, x: -200 }}
key={item.slug}
>
<CartComponent item={item} />
</MotionBox>
);
})}
</AnimatePresence>
</Box>
</VStack>
</PageLayout>
</>
);
};
export default Cart;
hmm sussy!
I have a custom Input Box and when I type inside a custom input component It'll re-render the typed input inside.
import {
Badge,
Box,
CloseButton,
Grid,
GridItem,
Input,
Text
} from "#chakra-ui/react";
import React, { useEffect, useState } from "react";
function InputTag(props) {
const [tags, setTags] = useState(props.values);
const removeTag = (index) => {
setTags(tags.filter((_, i) => i !== index));
};
const addTag = (event) => {
if (event.target.value !== "") {
setTags([...tags, event.target.value]);
props.setFieldValue("tags", [...tags, event.target.value]);
event.target.value = "";
}
};
useEffect(() => {
props.show === false && setTags([]);
}, [props.show]);
//update values based on click suggestions
useEffect(() => {
setTags([props.values, props.suggTag]);
}, [props.suggTag, props.values]);
return (
<Box
display={"flex"}
border="1px"
borderColor={"gray.200"}
borderRadius={"md"}
padding={2}
>
<Grid templateColumns="repeat(3, 1fr)" gap={2} overflow="visible">
{tags &&
tags.map((tag, index) => (
<GridItem key={index}>
<Badge
variant="solid"
colorScheme={"purple"}
display={"flex"}
borderRadius="full"
justifyContent="space-between"
alignItems="center"
gap={2}
>
<Text>{tag}</Text>
<CloseButton onClick={() => removeTag(index)} />
</Badge>
</GridItem>
))}
</Grid>
<Input
type="text"
name="tags"
id="tags"
variant={"unstyled"}
placeholder="Add Tag"
_placeholder={{ fontsize: "md" }}
onChange={props.handleChange}
onBlur={props.handleBlur}
onError={props.errors}
onKeyUp={(event) =>
event.key === "Enter" ? addTag(event) && event.preventDefault() : null
}
/>
</Box>
);
}
export default InputTag;
Here, when I hit enter It'll render them inside the custom Input Box
I Inserted a custom array of strings as "ex_Tag" inside Previewer.js so that when I click on the word in array, it'll also get rendered inside custom input as well.
function NewUploader({ isOpen, onClose }) {
const cancelRef = useRef();
const ex_tags = ["Design", "Strategy", "Human Centered Design"];
const [show, Setshow] = useState(true);
const [suggTag, setSuggTag] = useState();
const initialValues = {
files: null,
tags: []
};
const validationSchema = yup.object({
files: yup.mixed().required("File is Required"),
tags: yup.mixed().required("tags required")
});
const onSubmit = (values, actions) => {
const formData = new FormData();
formData.append("files", values.files[0]);
formData.append("tags", values.tags);
for (var pair of formData.entries()) {
console.log(pair[0] + ", " + pair[1]);
}
actions.setSubmitting(false);
actions.resetForm();
Setshow(!show);
onClose();
};
const handlethis = (e) => {
e.preventDefault();
};
//insert suggested word to useState so i can pass it to custom input
const handleClick = (tag) => {
setSuggTag(tag);
};
return (
<Modal isOpen={isOpen} onClose={onClose} isCentered>
{/* update code on model here */}
<ModalOverlay />
<ModalContent>
<ModalHeader>
<Text fontWeight={"bold"} color="gray.900">
Upload Buddy
</Text>
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Flex direction="column" gap={3}>
<Box>
<Text fontWeight={"normal"} color="gray.700">
This learning contentwill not be summarised. to summarize your
content, use{" "}
<Link color={"purple.400"}>Create Knowledge Nugget</Link> option
instead.
</Text>
</Box>
<Box>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
{(formik) => (
<Form
onSubmit={handlethis}
autoComplete="off"
encType="multipart/form-data"
>
<FormLabel htmlFor="file">
<Text
fontSize="sm"
fontWeight="normal"
color="gray.900"
fontFamily={"body"}
>
Upload files
</Text>
</FormLabel>
{/* drag droop sec */}
{formik.isSubmitting ? (
<>
<Grid
templateColumns="repeat(3, 1fr)"
gap={2}
overflow="hidden"
>
{formik.values.files &&
formik.values.files.map((file, index) => (
<GridItem key={index}>
<Badge
variant="solid"
borderRadius="xl"
colorScheme={"gray"}
w={file.name.length * 4}
h="8"
display="flex"
justifyContent="center"
alignItems="center"
my={2}
>
<Text fontFamily={"body"}>{file.name}</Text>
<CloseButton colorScheme={"blackAlpha"} />
</Badge>
</GridItem>
))}
</Grid>
<Progress colorScheme={"yellow"} isIndeterminate />
</>
) : (
<>
<Dragdrop setFieldValue={formik.setFieldValue} />
<Grid
templateColumns="repeat(3, 1fr)"
gap={2}
overflow="hidden"
>
{formik.values.files &&
formik.values.files.map((file, index) => (
<GridItem key={index}>
<Badge
variant="solid"
borderRadius="xl"
colorScheme={"gray"}
w={file.name.length * 4}
h="8"
display="flex"
justifyContent="space-between"
alignItems="center"
my={2}
>
<Text fontFamily={"body"}>{file.name}</Text>
<CloseButton colorScheme={"blackAlpha"} />
</Badge>
</GridItem>
))}
</Grid>
{formik.errors.files && formik.touched.files && (
<Text fontFamily={"body"} color="red">
{formik.errors.files}
</Text>
)}
</>
)}
<FormErrorMessage>
<ErrorMessage name="file" />
</FormErrorMessage>
<FormLabel htmlFor="tags">
<Text
fontSize="sm"
fontWeight="normal"
color="gray.900"
fontFamily={"body"}
>
Tags
</Text>
</FormLabel>
<InputTag
setFieldValue={formik.setFieldValue}
handleChange={formik.handleChange}
handleBlur={formik.handleBlur.call}
values={formik.values.tags}
show={show}
suggTag={suggTag}
/>
{formik.errors.tags && formik.touched.tags && (
<Text fontFamily={"body"} color="red">
{formik.errors.tags}
</Text>
)}
<FormErrorMessage>
<ErrorMessage name="tags" />
</FormErrorMessage>
<Box
aria-invalid="true"
display={"flex"}
flexDir="row"
gap={2}
my={2}
>
<Text fontFamily={"body"}>Suggested</Text>
<Grid
templateColumns="repeat(3, 1fr)"
gap={2}
overflow="hidden"
>
{ex_tags.map(
(tag, index) => (
<GridItem key={index}>
//I inserted on click call here
<Box onClick={handleClick(tag)}>
<Badge
variant={"subtle"}
borderRadius="lg"
colorScheme={"gray"}
_hover={{
cursor: "pointer",
bgColor: "gray.200"
}}
>
<Text fontFamily={"body"}>{tag}</Text>
</Badge>
</Box>
</GridItem>
),
this
)}
</Grid>
</Box>
<Box display={"flex"} justifyContent="center" my={3}>
<Button
type="button"
ref={cancelRef}
colorScheme="yellow"
isLoading={formik.isSubmitting}
onClick={formik.handleSubmit}
>
<Text
fontWeight="bold"
fontSize="18px"
color="gray.900"
fontFamily={"body"}
>
Submit
</Text>
</Button>
</Box>
</Form>
)}
</Formik>
</Box>
</Flex>
</ModalBody>
</ModalContent>
</Modal>
);
}
export default NewUploader;
but It seems when I render them to the screen it will come out as I triggered the onClick even though I didn't.
For now I commented out the useEffect func inside input component
I have uploaded it to code sandbox Bellow.
https://codesandbox.io/s/amazing-heyrovsky-9kr0ex?file=/src/Previewer.js
I want to change my render in the same page when i click on next button. In my component i have my state next, setNext initialize to false. The onPress to my button i change my state to true, but nothing happen when i click to the next button !
Here you can see the Step1 to Step2 and understand more what i need ^^
const [next, setNext] = useState(false);
{!next ? (
//Step1
<BigButton
title="Suivant"
onPress={() => {
setNext(true);
}}
/>) : ( // Step2 )
}
And all my code here :
import React, { useState } from "react";
import { useNavigation } from "#react-navigation/core";
import BigButton from "../components/BigButton";
import BigTextInfos from "../components/BigTextInfos";
export default function SignUpScreen({ setToken }) {
const [next, setNext] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const toggleSwitchPassword = () => {
setShowPassword((prev) => !prev);
};
return (
<>
{!next ? ( // STEP 1
<View style={{ marginTop: 60 }}>
<BigTextInfos title="S'inscrire" subtitle="Vous êtes :" />
<View>
<View>
<TouchableHighlight
style={[styles.input, styles.inputGender]}
onPress={() => setGender("Mme")}
>
<Text style={[styles.darkGrey]}>Mme</Text>
</TouchableHighlight>
<TouchableHighlight
style={[styles.input, styles.inputGender]}
onPress={() => setGender("M.")}
>
<Text style={[styles.darkGrey]}>M.</Text>
</TouchableHighlight>
</View>
<TextInput
style={[styles.input]}
placeholder="Prénom"
placeholderTextColor={colors.darkgrey}
/>
<TextInput
style={[styles.input]}
placeholder="Nom"
placeholderTextColor={colors.darkgrey}
/>
<BigButton
title="Suivant"
onPress={() => {
setNext(true);
}}
/>
</View>
</View>
) : ( // STEP 2
<View style={{ marginTop: 60 }}>
<BigTextInfos title="S'inscrire" subtitle="Finalisez l'inscription" />
<View>
<TextInput
style={[styles.input]}
placeholder="Email"
placeholderTextColor={colors.darkgrey}
/>
<View style={[styles.input]}>
<TextInput
style={{ width: 300 }}
placeholder="Mot de passe"
placeholderTextColor={colors.darkgrey}
color={colors.dark}
secureTextEntry={showPassword ? true : false}
/>
{showPassword ? (
<Feather
name="eye-off"
size={24}
color={colors.grey}
onPress={() => {
toggleSwitchPassword();
}}
/>
) : (
<Feather
name="eye"
size={24}
color={colors.grey}
onPress={() => {
toggleSwitchPassword();
}}
/>
)}
</View>
<BigButton
title="S'inscrire"
empty="false"
onPress={async () => {
console.log("s'inscrire");
const userToken = "secret-token";
setToken(userToken);
}}
/>
</View>
</View>
)}
</>
);
}
Its a bit odd that its not working, try different approach - separate the return logic inside a function and call the function on render. It should look a bit like this
const [next,setNext] = useState(false)
const handleSteps = () => {
if(next){
return <BigButton
title="Suivant"
onPress={() => {
setNext(true);
}}/>
}
return <SmallButton /> //here goes the other component
}
and then call that handleSteps function inside your return
return(
{handleSteps()}
)
I have working code in App.jsx. Everything is working when this written together in one file.
const App = props => {
const [cartProducts, setCartProducts] = useState([]);
const [products, setProducts] = useState(getProducts());
//const [searchValue, setSearchValue] = useState();
const handleAddProductToCart = productID => {
setCartProducts([...cartProducts, productID]);
};
const handleRemoveFromCart = productID => {
const newCartProducts = cartProducts.filter(id => id !== productID);
setCartProducts(newCartProducts);
};
/*const filterItems = ({ description, title }) => {
return title.toLocaleLowerCase().indexOf(searchValue.toLocaleLowerCase())
|| description.toLocaleLowerCase().indexOf(searchValue.toLocaleLowerCase())
}*/
return (
<>
<Header/>
<Search/>
<Sidebar/>
<div>
{products.map(product => {
const { id, title, description, image } = product;
let haveInCart = false;
cartProducts.forEach(productID => {
if (productID === id) {
haveInCart = true;
}
});
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<CardText style={{ border: 'none' }} className="custom-card-text">{description}</CardText>
<FontAwesomeIcon icon={faCartPlus} className="add-icon" onClick={() => handleAddProductToCart(id)} />
</CardBody>
</Card>
);
})}
<h2>Your Cart</h2>
{cartProducts.length > 0
? cartProducts.map(productID => {
const productIndex = products.findIndex(product => {
return product.id === productID;
});
let { id, title, image } = products[productIndex];
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<FontAwesomeIcon icon={faTrash} className="remove-icon" onClick={() => handleRemoveFromCart(id)} />
</CardBody>
</Card>
);
})
: "Yor Cart is Empty :("}
</div>
</>
)
}
export default App;
I want to put product Card and cart Card into it's own component. And when I'm doing it, like this
const Product = ({product}) => {
const { id, title, description, image } = product;
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<CardText style={{ border: 'none' }} className="custom-card-text">{description}</CardText>
<FontAwesomeIcon icon={faCartPlus} className="add-icon" /*onClick={() => handleAddProductToCart(id)}*/ />
</CardBody>
</Card>
)
}
I'm not getting properties of product in my Card. I want to make my code better organized and save it's functionality. How to access those states from Product and Cart component?
EDIT
Here's the link to codesandbox
https://codesandbox.io/s/late-cookies-r2inh?file=/src/App.jsx&fbclid=IwAR38tcE39tVL51YpG4_6A1HRz-kth1GSIocQWMPrU3QXepc5CHUNn-ZqiG8
EDIT 2 How I can make items in cart be displaying beside Product component, on the left side? Should I create entire Cart component for it?
Your Product.jsx file should look like this:
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faCartPlus } from "#fortawesome/free-solid-svg-icons";
import Card from "react-bootstrap/Card";
import CardBody from "react-bootstrap/Card";
import CardImg from "react-bootstrap/CardImg";
import CardTitle from "react-bootstrap/Card";
import CardText from "react-bootstrap/Card";
const Product = ({ product, handleAddProductToCart }) => {
const { id, title, description, image } = product;
return (
<Card key={id} className="item-card">
<CardImg
src={image}
alt={title}
className="item-img"
style={{ height: "260px" }}
/>
<CardBody style={{ border: "none" }} className="custom-card-body">
<CardTitle style={{ border: "none" }} className="custom-card-title">
{title}
</CardTitle>
<CardText style={{ border: "none" }} className="custom-card-text">
{description}
</CardText>
<FontAwesomeIcon
icon={faCartPlus}
className="add-icon"
onClick={() => handleAddProductToCart(id)}
/>
</CardBody>
</Card>
);
};
export default Product;
And in your App.jsx you can map the products array like this:
{products.map((product) => (
<Product
product={product}
key={product.id}
handleAddProductToCart={handleAddProductToCart}
/>
))}
EDIT:
https://codesandbox.io/s/determined-swartz-5q2fo
I edited the codesandbox, i made the Product component accept both add and remove product callback and the "haveInCart" prop. It will decide which icon and which callback to use base on that prop. I'm not sure about this approch tho
I experienced React before and trying to learn React Native so here is my problem about react-navigation
I have some separated class or js files for react-navigation
main.js
type Props = {};
class Main extends Component<Props> {
componentDidMount() {
SplashScreen.hide();
}
render() {
return (
<Container>
<MainPostsList />
</Container>
)
}
};
const Stack = createStackNavigator();
//its not a class for this navigation thing
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={Main} />
<Stack.Screen name="Post" component={PostsPage} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default App;
postlist.js
export default class MainPostLists extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
data: [],
}
}
componentDidMount() {
getMainPosts().then(data => {
this.setState({
isLoading: false,
data: data
})
}, error => {
Alert.alert('An error has occurred', 'Please try again later.')
})
}
render() {
console.log(this.state.data.data);
let view = this.state.isLoading ? (
<View>
<ActivityIndicator animating={this.state.isLoading} size={"large"} style={{paddingTop: 40}} />
</View>
) : (
<List
dataArray={this.state.data.data}
renderRow={(item) => {
return <MenuPostItem data={item} />
}} />
)
return (
<Container>
<Content>
{view}
</Content>
</Container>
)
}
}
postlistitem.js
export default class MenuPostItem extends Component {
constructor(props) {
super(props);
this.data = props.data;
}
render() {
console.log(this.data)
const goToPostPage = (postlink) => {
console.log("Going to Post Page " + postlink);
this.props.navigation.navigate('Post')
};
return (
<ListItem button onPress={() => {goToPostPage(this.data.postlink)}} onLongPress>
<Left>
{this.data.type === 'video' ? (
<Thumbnail style={{ width: 150, height: 84, borderRadius: 0 }} source={{
uri: `http://` + hostname + `:5000/media/streamimage?src=${this.data.media.videothumbsrc}`
//uri: ImageThumbTest
}} />
) : (null)}
{this.data.type === 'text' ? (
<Thumbnail style={{ width: 150, height: 84, borderRadius: 0 }} />,
<Text style={{paddingLeft: 40, paddingRight: 40}}>Text Post</Text>
) : (null)}
</Left>
<Body>
<Text>{this.data.title}</Text>
<Text note numberOfLines={3}>{this.data.description}</Text>
</Body>
</ListItem>
)
}
}
this error appears on Android as I click on an item from the list:
it was supposed to go to a post dynamic page
MenuPostItem doesn't have any access to navigation props.
Here how you get access to navigation props
Passing the navigation prop to MenuPostItem from MainPostLists component
<List
dataArray={this.state.data.data}
renderRow={(item) => {
return <MenuPostItem data={item} navigation={this.props.navigation} />;
}}
/>;
Using useNavigation hooks (you need to change your MenuPostItem to the functional component to use useNavigation hook)
a minimal example
import * as React from "react";
import { Button } from "react-native";
import { useNavigation } from "#react-navigation/native";
function MenuPostItem() {
const navigation = useNavigation();
return (
<Button
title="go to post"
onPress={() => {
navigation.navigate("Post");
}}
/>
);
}
learn more about useNavigation
create a function for list items like below
const MenuPostItem = ({data, onPress}) = > {
return (
<ListItem button onPress={() => onPress('Post')}>
<Left>
{data.type === 'video' ? (
<Thumbnail
style={{ width: 150, height: 84, borderRadius: 0 }}
source={{uri: `http://` + hostname + `:5000/media/streamimage?src=${data.media.videothumbsrc}`}}
/>
) : (null)}
{data.type === 'text' ? (
<Thumbnail style={{ width: 150, height: 84, borderRadius: 0 }} />,
<Text style={{paddingLeft: 40, paddingRight: 40}}>Text Post</Text>
) : (null)}
</Left>
<Body>
<Text>{data.title}</Text>
<Text note numberOfLines={3}>{data.description}</Text>
</Body>
</ListItem>
)}
export default MenuPostItem;
and then in your MainPostLists.js file -
<List
dataArray={this.state.data.data}
renderRow={(item) => {
return <MenuPostItem data={item} navigation={this.props.navigation.navigate} />;
}}
/>;