I have implement a function to navigate to new screen when click a button in using media list in react bootstrap, but that function automatically called when screen is loading,
this is my code
function News() {
const history = useHistory()
const [eventData, setEventdata] = useState('');
const [MemberOffer, setMemberOffer] = useState('');
const [Loading, setLoading] = useState(true);
const [Loading2, setLoading2] = useState(true);
useEffect(() => {
getDatafromserver()
getallmemebroffers()
Logincheck()
}, []);
async function getDatafromserver() {
console.log("inside getDatafromserver funcation")
try {
await fetch('http://124.43.17.60:4000/getallevent')
.then((response) => response.json())
.then((json) => setEventdata(json.Rows))
.catch((error) => alert('Please check your network'))
.finally(() => setLoading(false))
console.log("rana data", eventData)
console.log("loding....", Loading)
} catch (error) {
console.log("error when get data from server")
}
}
async function getallmemebroffers() {
console.log("inside memebr offer funcation")
try {
await fetch('http://124.43.17.60:4000/memoffers')
.then((response) => response.json())
.then((json) => setMemberOffer(json.news))
.catch((error) => alert('Please check your network'))
.finally(() => setLoading2(false))
console.log("Member offers", MemberOffer)
console.log("loding....", Loading2)
} catch (error) {
console.log("error when get data from server")
}
}
const Logincheck = () => {
console.log("inside login check")
try {
Axios.get("http://124.43.17.60:4000/loging_check")
.then((response) => {
console.log("res cookie", response)
})
} catch (error) {
console.log("No internet")
}
}
function editNews(){
history.push('/admin/edit-news')
}
return (
<div className='home' >
<br></br>
<Card style={{ height: 'auto' }} >
{/* memebr offer */}
<Card.Header style={{ borderColor: 'white', fontSize: '30px', fontFamily: 'Quicksand-Bold' }}>Tech News</Card.Header>
{Loading2 ? <Loader type="Circles" color="#00BFFF" height={80} width={80} /> : (
<div>
{MemberOffer.map((object, index) => (
// <p key={index.id}>{object.event_name}</p>
<Card.Body >
<ul className="list-unstyled" style={{ marginLeft: '20px' }}>
<Media as="li">
<img
width={72}
height={72}
className="mr-3"
src={object.offer_image}
alt="Generic placeholder"
/>
<Media.Body style={{ marginLeft: '10px' }}>
<h5 style={{ fontSize: '20px', fontFamily: 'Quicksand-Bold' }}>{object.offer_name}</h5>
<p style={{ fontSize: '15px', fontFamily: 'Quicksand-Medium', color: '#707070' }}>
{object.offer_content}
</p>
</Media.Body>
<Button variant="primary" onClick={editNews()}>Edit</Button>
</Media>
<br></br>
</ul>
</Card.Body>
))}
</div>
)}
</Card>
</div >
)
}
export default News
when I'm reload the page this editNews() function already called and navigate to EditNews page without click the Edit button. Can any one tell me what I am doing wrong with in this code and please help me to solve this problem
Do not call the function in onClick. This should work.
<Button variant="primary" onClick={editNews}>Edit</Button>
Related
I am still new.
I am making my portfolio.But I got problem.
I am trying to get data from django rest framework with axios. It says I got no error.
I want to display the data in cards components.
But still it does not show data in the browser.
How can I solve this problem?
Thank you in advance.
//App.tsx
const App: React.FC = () => {
const [loading, setLoading] = useState(false);
const [results, setResults] = useState<EventProps[]>([]);
const url = "http://127.0.0.1:8000/events/lists/";
useEffect(() => {
const getEventsData = async () => {
try {
const res = await axios.get<EventProps[]>(url).then((res) => {
setResults(res.data);
setLoading(true);
// console.log(res.data.results.event_id);
console.log(res);
console.log(res.data);
});
} catch (err) {
console.log(err);
}
};
getEventsData();
}, []);
return (
<>
<div className="wholeheader">
<MantineProvider
inherit
theme={{ defaultGradient: { from: "blue", to: "teal", deg: 20 } }}
>
<Group position="apart" grow>
<Center
sx={(theme) => ({
height: 170,
backgroundImage: theme.fn.gradient(),
color: theme.white,
})}
>
<Logo />
<div className="header">
<HeaderTabsColored {...HeaderProps} />
<LoginAndRegiInHeader />
</div>
<div className="searchbar">
<SearchBar />
</div>
</Center>
</Group>
</MantineProvider>
</div>
{loading ? (
<Fragment>loading..</Fragment>
) : (
Object.values(results).map((result: EventProps) => (
<EventsCard
key={result.event_id}
event_id={result.event_id}
title={result.title}
description={result.description}
dateTime={result.dateTime}
capacity={result.capacity}
EventImage1={result.EventImage1}
EventImage2={result.EventImage2}
EventImage3={result.EventImage3}
location={result.location}
host={result.host}
/>
))
)}
<br />
<br />
<Page />
</>
);
};
export default App;
//Events.tsx
[data in the browser][1]
import { EventProps } from "../types/EventsProps";
import { Grid } from "#mantine/core";
import axios from "axios";
import { ThemeContext } from "#emotion/react";
import eventImage from "../Images/Events/eventImage.jpg";
const useStyles = createStyles((theme) => ({
card: {
backgroundColor:
theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.white,
},
section: {
borderBottom: `1px solid ${
theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
paddingLeft: theme.spacing.md,
paddingRight: theme.spacing.md,
paddingBottom: theme.spacing.md,
},
like: {
color: theme.colors.red[6],
},
label: {
textTransform: "uppercase",
fontSize: theme.fontSizes.xs,
fontWeight: 700,
},
}));
// {EventImage1, EventImage2, EventImage3, event_id, location, description, capacity, title, host,dateTime}:
const EventsCard: React.FC<EventProps> = (props) => {
const { classes, theme } = useStyles();
const [opened, setOpened] = useState(false);
return (
<Grid>
<Grid.Col span={4} key={props.event_id}>
<Card withBorder radius="md" p="md" className={classes.card}>
<Card.Section>
<Image
className="image"
src={props.EventImage1}
alt={props.title}
height={300}
width={342}
/>
<Image
className="image"
src={props.EventImage2}
alt={props.title}
height={300}
width={342}
/>
<Image
className="image"
src={props.EventImage3}
alt={props.title}
height={300}
width={342}
/>
</Card.Section>
<Card.Section className={classes.section} mt="md">
<Group position="apart">
<Text size="lg" weight={800}>
{props.title}
<br />
{props.dateTime}
</Text>
<Badge size="sm">{props.location}</Badge>
</Group>
<Text size="lg" weight={500}>
定員:{props.capacity}名
</Text>
<Text size="sm" mt="xs">
{props.description}
</Text>
</Card.Section>
<Card.Section className={classes.section}>
<Text mt="md" className={classes.label} color="dimmed">
host
</Text>
<Text size="sm">{props.host}</Text>
</Card.Section>
</Card>
</Grid.Col>
</Grid>
);
};
export default EventsCard;
How can I get the clicked card only to change its string from 'not captured' to 'captured'? Right now, all cards' strings say 'captured' even if I click on only one. I think the problem is that the captured state updates for all the cards and I can't get the captured state to update for the single clicked card. It's an onChange event and a checkbox.
import React, { useState, useEffect } from 'react'
import PokemonCard from '../components/PokemonCard';
const Pokedex = () => {
const [pokemons, setPokemons] = useState([]);
const [captured, setCaptured] = useState(false )
const URL = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
const fetchingPokemons = async () => {
const res = await fetch(URL);
const data = await res.json();
// console.log(data)
setPokemons(data.results)
}
useEffect(() => {
fetchingPokemons()
}, [URL])
const toggleCaptured= (e, id) => {
console.log(id)
if(id && e) {
console.log('oh')
setCaptured(captured => !captured)
}
let capturedPkm = [];
let notCapturedPkm = [];
pokemons.forEach(i => {
if(captured === true) {
capturedPkm.push(pokemons[i])
} else {
notCapturedPkm.push(pokemons[i])
}
})
console.log('captured', capturedPkm, 'not captured', notCapturedPkm)
}
return (
<>
<div style={{display: 'flex', flexWrap: 'wrap', justifyContent: 'space-evenly'}}>
{pokemons ? pokemons.map((pokemon) => {
return (
<>
<div style={{ width: '235px' }} >
<PokemonCard
pokemon={pokemon}
name={pokemon.name}
url={pokemon.url}
key={pokemon.id}
captured={captured}
toggleCaptured={toggleCaptured}
/>
</div>
</>
)
}) : <h1>Loading...</h1>}
</div>
</>
)
}
export default Pokedex
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import PokemonIcon from './PokemonIcon';
const PokemonCard = (props) => {
const { url, captured, toggleCaptured } = props
const URL = url
const [pokemonCard, setPokemonCard] = useState([])
const fetchingPokemonCard = async () => {
const res = await fetch(URL);
const data = await res.json();
//console.log(data)
setPokemonCard(data)
}
useEffect(() => {
fetchingPokemonCard()
}, [URL])
return (
<>
<div className='pokemon-card' style={{
height: '250px',
maxWidth: '250px',
margin: '1rem',
boxShadow: '5px 5px 5px 4px rgba(0, 0, 0, 0.3)',
cursor: 'pointer',
}} >
<Link
to={{ pathname: `/pokemon/${pokemonCard.id}` }}
state={{ pokemon: pokemonCard, captured }}
style={{ textDecoration: 'none', color: '#000000' }}>
<div
style={{ padding: '20px', display: 'flex', justifyContent: 'center', alignItems: 'center' }} >
<PokemonIcon img={pokemonCard.sprites?.['front_default']} />
</div>
</Link>
<div style={{ textAlign: 'center' }}>
<h1 >{pokemonCard.name}</h1>
<label >
<input
type='checkbox'
defaultChecked= {captured}
onChange={(e) => toggleCaptured(e.target.checked, pokemonCard.id)}
/>
<span style={{ marginLeft: 8, cursor: 'pointer' }}>
{captured === false ? 'Not captured!' : 'Captured!'}
{console.log(captured)}
</span>
</label>
</div>
</div>
<div>
</div>
</>
)
}
export default PokemonCard
Use an object as state:
const [captured, setCaptured] = useState({})
Set the toggle function:
const toggleCaptured = (checked, id) => {
const currentChecked = { ...captured }; // Create a shallow copy
console.log(id)
if (checked) {
currentChecked[id] = true;
} else {
delete currentChecked[id];
}
setCaptured(currentChecked); // Update the state
let capturedPkm = pokemons.filter(({id}) => currentChecked[id]);
let notCapturedPkm = pokemons.filter(({id}) => !currentChecked[id]);
console.log('captured', capturedPkm, 'not captured', notCapturedPkm)
}
The PokemonCard should look like this
<PokemonCard
pokemon={pokemon}
name={pokemon.name}
url={pokemon.url}
key={pokemon.id}
captured={captured[pokemon.id]} // Here
toggleCaptured={toggleCaptured}
/>
I have a table in my project and I have an edit / view / add page that I can access from this table. My goal is to send the clicked data to the other component without any problem, but no matter how hard I try, I get an undefined error and the project is broken. I would be glad if you could help.
I am sharing my codes from parent to child component
Table page.
import React, { useState, useEffect, useCallback, useMemo } from "react";
import ManagementTable from '../components/ManagementTable'
import {
getApps,
updateStopRisk,
countLiveCountry,
updateAppShow,
deleteApp,
} from "../api/apiCalls";
import VisibilityIcon from "#material-ui/icons/Visibility";
import DeleteIcon from "#material-ui/icons/Delete";
import EditIcon from "#material-ui/icons/Edit";
import Switch from "#material-ui/core/Switch";
import DeleteModal from "../components/DeleteModal";
import { Link } from "react-router-dom";
const Management = () => {
const [apps, setApps] = useState([]);
const [modalVisible, setModalVisible] = useState(false);
const [currentApp, setCurrentApp] = useState("");
const [appID, setAppID] = useState(0);
const fetchData = useCallback(async () => {
const { data: appsResponse } = await getApps();
const countLiveCountries = await fetchLiveCountriesForApps(appsResponse);
setApps(
appsResponse.map((app, idx) => ({
...app,
countLiveCountry: countLiveCountries[idx],
}))
);
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
const fetchLiveCountriesForApps = async (appwLive) => {
const countLiveCountries = await Promise.all(
appwLive.map((app) => countLiveCountry(app.appID))
);
return countLiveCountries.map(({ data: liveCountries }) => liveCountries);
};
const removeApp = async () => {
await deleteApp(appID);
setModalVisible(false);
fetchData();
};
const onClickCancel = () => {
setModalVisible(false);
};
const columns = useMemo(() => [
{
Header: "Application Name",
accessor: "app_name",
},
{
Header: "Business Area",
accessor: "businessarea.businessarea_name",
},
{
Header: "Live Plants",
accessor: "countLiveCountry",
},
{
Header: "Line Stop Risk",
accessor: "app_stoprisk",
Cell: ({ row: { original } }) => {
const changeCheck = async (id) => {
await updateStopRisk(id);
fetchData();
};
return (
<input
checked={original.app_stoprisk}
onClick={() => {
changeCheck(original.appID);
}}
id="appStopRisk"
type="checkbox"
style={{ width: 18, height: 18, marginTop: 5 }}
/>
)
},
sortType: (a, b, id) => {
if (a.original[id] > b.original[id]) return -1;
if (b.original[id] > a.original[id]) return 1;
},
},
{
Header: "Actions",
Cell: ({ row: { original } }) => {
const changeTrack = async (id) => {
await updateAppShow(id);
fetchData();
};
return (
<>
<Link
className="btn btn-manage-link btn-sm col-2"
to={{
pathname: `/management/${original.app_name}`,
mode: "view",
id: original.appID
}}
>
<VisibilityIcon></VisibilityIcon>
</Link>
<Link
to={{
pathname: `/management/${original.app_name}`,
mode: "edit",
id: original.appID
}}
className="btn btn-manage-link btn-sm col-2"
>
<EditIcon></EditIcon>
</Link>
<button
onClick={() => {
setModalVisible(true);
setCurrentApp(original.app_name);
setAppID(original.appID);
}}
className="btn btn-manage-link btn-sm col-3"
>
<DeleteIcon></DeleteIcon>
</button>
<Switch
onClick={() => changeTrack(original.appID)}
checked={original.app_show}
className="col-3"
></Switch>
</>
)
},
},
],
[fetchData]
);
return (
<div className="container">
<h2 style={{ float: "left", font: "bold" }}>Management</h2>
<div style={{ float: "right" }}>
<Link className="btn btn-danger btn-sm" to={{ pathname: `/management/add`, mode: "add" }}>
Add New App
</Link>
<Link className="btn btn-danger btn-sm ml-3" exact to="/management/plants">
Plant Management
</Link>
</div>
<ManagementTable columns={columns} data={apps} />
<DeleteModal
message={<strong>{currentApp}</strong>}
variety="app"
onClickCancel={onClickCancel}
onClickOk={removeApp}
visible={modalVisible}
/>
</div>
);
};
export default Management;
The page where I transfer the props.
import React, { useState, useEffect } from "react";
import Accordion from "../components/Accordion";
import Details from '../components/Details'
import {
getByIdApps,
} from "../api/apiCalls";
const ApplicationManagement = (props) => {
const [appById, setAppById] = useState([]);
const { id } = props.location;
const [selectOption, setSelectOption] = useState('add')
useEffect(() => {
getData();
getMode();
}, [])
const getData = async () => {
console.log(props.location.id)
if (props.location.id) {
await getByIdApps(props.location.id).then((response) => setAppById(response.data))
console.log(appById)
console.log(props)
}
else {
setSelectOption('add')
}
}
const getMode = () => props.location.mode ? setSelectOption(props.location.mode) : setSelectOption('add')
const handleOptionChange = (event) => {
console.log(event.target.value)
setSelectOption(event.target.value)
}
return (
<>
<div style={{ margin: 20 }}>
<h1>
{appById.app_shortcode} - {appById.app_fullname}
</h1>
<div className="float-right mb-auto">
<label><input type="radio" value="view" checked={selectOption === 'view'} onChange={handleOptionChange} />View</label>
<label> <input type="radio" value="add" checked={selectOption === 'add'} onChange={handleOptionChange} />Add</label>
<label> <input type="radio" value="edit" checked={selectOption === 'edit'} onChange={handleOptionChange} />Edit</label>
</div>
<br></br>
<div style={{ marginLeft: 50, marginRight: 50 }} >
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Links</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Factory Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Issues Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Middleware Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
</div>)
{selectOption === 'add' ? (
<div>
Add Mode
</div>
) : selectOption === 'view' ? (<div>View Mode</div>) : (<div>eidt</div>)}
</div>
</>
);
};
export default ApplicationManagement;
and the section where the details are kept on the ApplicationManagement page (My code is quite long, I just share the problem part.)
import React, { useState, useEffect } from 'react'
import axios from "axios";
import {
getResponsibleTeams,
getBusinessAreas
} from '../api/apiCalls'
const Details = (props) => {
const [rTeams, setrTeams] = useState([]);
const [bAreas, setbAreas] = useState([]);
const { data } = props;
useEffect(() => {
async function fetchData() {
const getrTeams = await getResponsibleTeams();
const getbAreas = await getBusinessAreas();
axios.all([getrTeams, getbAreas]).then(
axios.spread((...allData) => {
const allrTeams = allData[0].data;
const allbAreas = allData[1].data;
setrTeams(allrTeams);
setbAreas(allbAreas);
})
);
}
fetchData();
}, []);
return (
<div>
<div
style={{
float: "left",
width: 1350,
height: 340,
}}
>
<div className="form-group">
<label style={{ float: "left" }} htmlFor="appFullName">
Frontend:{" "}
</label>
<input
id="appFullName"
type="text"
class="form-control"
placeholder="dsfdsdsf"
value={data.frontend.frontend_name} // error here
//onChange={handleInputChange}
name="appShortCode"
style={{ width: 400, marginLeft: 150 }}
/>
</div>
</div>
</div>
)
}
export default Details;
Later I realized that using asynchronous functions caused some problems. I came up with a solution to this and the problem was solved.
Error Code Here :
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>
and the solution to the problem
{appById &&
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>}
I am getting an infinite loop and I know the problem is because I am putting in brackets as the second argument the 'posts' and the 'setPost' inside the useEffect function, but I need the page to render whenever I add a new post, so the posts must be in brackets.
function Home() {
const {userData, setUserData} = useContext(userContext)
const [posts, setPost] = useState([])
const [createPost, setCreatePost] = useState('')
const handleToken = () => {
localStorage.removeItem('auth-token')
}
const token = localStorage.getItem("auth-token");
const handleOnSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:5000/posts', {textOfThePost: createPost}, {
headers: { 'auth-token': token },
})
.then((res) => {setCreatePost("")})
}
useEffect(() => {
axios.get('http://localhost:5000/posts')
.then(res => {
setPost(res.data)
})
}, [posts])
return (
<div className="home">
<div style={{display: 'flex', alignItems: 'center'}}>
<h1>this is the home: Welcome, {userData.username}</h1>
<Link style={{margin: 10}} to="/home">home</Link>
<Link style={{margin: 10}} to="/profile">profile</Link>
<Link style={{margin: 10}} onClick={handleToken} to="/">log out</Link>
</div>
<form onSubmit={handleOnSubmit}>
<input type="text" placeholder="What's happening?" value={createPost} onChange={e => setCreatePost(e.target.value)}/>
<button type="submit">tweet</button>
</form>
<div style={{display: 'flex', flexDirection: 'column'}}>
{posts.map(post => (
<div style={{border: '2px solid black', marginBottom: 10, marginRight: 'auto', marginLeft: 'auto', width: 300}} key={post._id}>
<div style={{display: 'flex', alignItems: 'center'}}>
<Avatar src={post.avatar}/>
<span style={{color: 'blue', marginLeft: 10}}>{post.name} <span style={{color: 'grey', fontSize: 11}}>#{post?.username}</span></span><br/>
</div>
<span>{post.textOfThePost}</span><br/>
<span>{moment(post.date).format('lll')}</span>
</div>
)).reverse()}
</div>
</div>
)
}
The problem here is the dependency array for useEffect (and similar hooks) doesn't use deep comparison (for performance reasons).
That is, whenever you get new data via Axios, res.data is a new JavaScript object and as you assign it to state, the effect dependency considers it an entirely changed object and runs the effect again, etc.
The easiest fix is to use a deep-comparing useEffect such as https://github.com/kentcdodds/use-deep-compare-effect .
You are not using posts in your effect, so it shouldn't be in your dependency array at all. One solution for your issue might be getting the posts in the first render, just once, then whenever you create a post, using the response updating the posts state.
const posts = [
{ id: "1", text: "foo" },
{ id: "2", text: "bar" },
{ id: "3", text: "baz" }
];
const API = {
getPosts: () =>
new Promise((resolve) => setTimeout(() => resolve(posts), 2000)),
createPost: () =>
new Promise((resolve) =>
setTimeout(() => resolve({ id: "3", text: "fizz" }), 1000)
)
};
function Posts() {
const [posts, setPosts] = React.useState([]);
React.useEffect(() => {
API.getPosts().then(setPosts);
}, []);
function handleOnSubmit() {
API.createPost().then((res) => setPosts((prev) => [...prev, res]));
}
return (
<div>
<div>
<button onClick={handleOnSubmit}>Create Post</button>
</div>
{!Boolean(posts.length) ? (
<span>Loading posts...</span>
) : (
posts.map((post) => <div>{post.text}</div>)
)}
</div>
);
}
ReactDOM.render(
<Posts />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root" />
Don't bother the API part, I'm just mimicking your requests. The important part is after creating the post, using the response, and updating the state.
As the title says. Every time I enter a letter into my SearchBar component it closes the keyboard and I'm forced to reopen it by pressing the search bar again. As you can imagine that's quite annoying.
Here's the code for the function component
import React, { useState, useEffect } from "react";
import { View, Text, FlatList } from "react-native";
import { Button, Searchbar } from "react-native-paper";
import { useSelector } from "react-redux";
import {
useFonts,
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic,
} from "#expo-google-fonts/poppins";
import Header from "../navigation/Header";
export default function AktSelect({...props}) {
const [data, setData] = useState([]);
const [value, setValue] = useState("");
const [akt, setAkt] = useState([]);
const [ime, setIme] = useState("");
const [opis, setOpis] = useState("");
const [mjesto, setMjesto] = useState("");
const [tip, setTip] = useState("");
const users = useSelector((state) => state.users);
useEffect(() => {
fetch("http://192.168.1.5:8000/fetchActivities", {
method: "POST",
headers: {
Accept: "application/json",
"Content-type": "application/json charset=utf-8",
},
body: JSON.stringify({
team: 'team'
}),
})
.then((res) => res.json())
.then((res) => setAkt(res));
}, []);
fetchData = async () => {
fetch("http://192.168.1.5:8000/fetchActivity", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
data: item_id,
}),
})
.then((res) => res.json())
.then((res) => {
setIme(res[0].title);
setOpis(res[0].description);
setMjesto(res[0].location);
setTip(res[0].activity_type_id);
});
};
searchItems = (text) => {
const newData = akt.filter((item) => {
const itemData = `${item.title.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setData(newData);
setValue(text);
};
Item = ({ item }) => {
return (
<View>
<Text
style={{
padding: 10,
fontSize: 18,
fontFamily: "Poppins_600SemiBold",
}}
>
{item.title}{" "}
</Text>
<View
style={{
flexDirection: "row",
alignItems: "flex-end",
justifyContent: "flex-end",
}}
>
<Text style={{ padding: 10, fontFamily: "Poppins_400Regular" }}>
{item.start_time}{" "}
</Text>
<Button
mode="outlined"
onPress={() =>
props.navigation.navigate("Izmjena", {
name: item.title,
desc: item.description,
loc: item.location,
type: item.activity_type_id,
item_id: item.id,
})
}
style={{ marginRight: "3%", marginBottom: "1%", color: "#C5272F" }}
color="#C5272F"
>
Dalje
</Button>
</View>
</View>
);
};
renderHeader = () => {
return (
<Searchbar
placeholder="Type here..."
onChangeText={(text) => searchItems(text)}
value={value}
/>
);
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE"
}}
/>
);
};
const { navigation } = props;
return (
<View
style={{
flex: 1,
width: "98%",
alignSelf: "center",
justifyContent: "center",
}}
>
<Header title="Pretraživanje aktivnosti" navigation={navigation} />
<FlatList
data={data}
renderItem={({ item }) => <Item item={item} />}
keyExtractor={(item) => item.id.toString()}
ItemSeparatorComponent={renderSeparator}
ListHeaderComponent={renderHeader}
/>
</View>
);
}
I've converted it from a class component into a function component. Here's the old code
https://hatebin.com/inkmlddkpz
Oddly enough I found an answer not 3 minutes after this post
The issue was I had these 2 functions
renderHeader = () => {
return (
<Searchbar
placeholder="Type here..."
onChangeText={(text) => searchItems(text)}
value={value}
/>
);
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE"
}}
/>
);
};
Which caused a re-render on each keypress of the keyboard (hence the keyboard closing).
The fix was to move them outside the exported function.
function renderSeparator(){
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE"
}}
/>
);
}
function renderHeader({value}) {
return (
<Searchbar
placeholder="Type here..."
onChangeText={(text) => searchItems(text)}
value={value}
/>
);
}