useEffect not working with multiple dropdowns in Semantic UI React - javascript

I am using Semantic UI React.
The following JS code does not work for me:
import React, { useState, useEffect } from "react";
import { Dropdown, Form, Button } from "semantic-ui-react";
export const MovieDropdown = () => {
const [movie, setMovie] = useState("");
const [person, setPerson] = useState("");
const [movieOptions, setMovieOptions] = useState([]);
const [personOptions, setPersonOptions] = useState([]);
useEffect(() => {
Promise.all([
fetch("/people").then(res =>
res.json()
),
fetch("/movies").then(res =>
res.json()
)
])
.then(([res1, res2]) => {
console.log(res1, res2);
var make_dd = (rec) => {
rec.map(x => {
return {'key': x.name, 'text': x.name, 'value': x.name}
})
}
setPersonOptions(make_dd(res1))
setMovieOptions(make_dd(res2))
})
.catch(err => {
console.log(err);
});
});
return (
<Form>
<Form.Field>
<Dropdown
placeholder="Select Movie"
search
selection
options={movieOptions}
onChange={(e, {value}) => setMovie(value)}
/>
</Form.Field>
<Form.Field>
<Dropdown
placeholder="Select Person"
search
selection
options={personOptions}
onChange={(e, {value}) => setPerson(value)}
/>
</Form.Field>
</Form>
);
};
export default MovieDropdown;
Problem is that I lose the DB connection when running this component. I tried with MySQL and SQLite and it gives the same issue.
How to solve this? Should I have 1 fetch per component?
I thank you in advance.
Kind regards,
Theo

Well, I dont know about the DB Connetion, but the remmended way of calling api in useEffect is like this:
useEffect({
// your code here only once
},[])
OR,
useEffect({
// your code here will run whenever id changes
},[id])
Your useEffect will run on every render,which is not recommended time/ way to make api calls.

Related

Why my fetch is not working, while I use Usestate

I want to make a component, which should have an input and button. The button should do some kind of work, I want it to show the information that I need to receive with fetch. In this case my code is not working, it shows a lot of [objects], however I want it to show the information from the base. if you can please help... : )
import React, { useState } from 'react';
const App = () => {
const [User, setUser] = useState({num: ""})
const [Open, setOpen] = useState(false)
const users = () => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((json) => {
document.write(json);
});
};
return( <>
<input name="Num" />
<button onClick={users}> Click Me for users </button>
</>)
}
export default App ```
You should almost never use document.write
Following is one of they ways you can solve your problem
import React, { useState } from "react";
const App = () => {
const [User, setUser] = useState({ num: "" });
const [Open, setOpen] = useState(false);
const [users, setUsers] = useState([]);
const fetchAndSetUsers = () => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => {
setUsers(users);
});
};
return (
<>
<input name="Num" />
<button onClick={fetchAndSetUsers}> Click Me for users </button>
{users.map((user) => {
return <div>{user.name}</div>;
})}
</>
);
};
export default App;
Change the line of
document.write
to
setUsers(json)
You shouldn't manipulate UI directly in React using DOM methods since React uses Virtual DOM concept to update UI
document.write receive html element as parameter not a json object, if you just want to check if the fetch work you can do JSON.stringigy(json)
PS: sorry for my poor english

React native Pull to refresh is not working

I m trying to add pull to refresh to fetch my data from my api but it is not working and i can'y find the problem within the code:
const[refresh,setRefresh]=useState(true)
const onRefresh=()=>{
try{
axios
.get('http://192.168.1.17:8000/File/')
.then((response)=> {
setFile(response.data);
setFilteredFile(response.data)
setEmpty(false)
setRefresh(false);
})}
catch(error){console.log(error)
}
}
useEffect(()=>{
onRefresh()
},[])
<FlatList style={DocumentStyle.flatstyle}
keyExtractor={(item)=>item['id']}
data={filteredfile}
renderItem={renderItem}
onRefresh={()=>onRefresh()}
refreshing={refresh}
/>
never mind me everyone, i haven't set my refresh back to true after the useEffect set it to false
The error is due to not importing useState, but you also need to import useEffect. I also dont see where some of the props your passing to FlatList are being used. But here's a working sample:
import {useState, useEffect} from 'react';
const FlatList = ({file, refreshing, onRefresh}) => {
return (
<div>
<p>{file}</p>
<button onClick={() => onRefresh(2)}>Load another todo</button>
</div>
)
}
export default function App() {
const [refresh, setRefresh] = useState(true);
const [file, setFile] = useState('');
useEffect(() => onRefresh(), []);
const onRefresh = (id=1) => {
try {
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then(response => response.json())
.then(json => {
console.log(json)
setFile(JSON.stringify(json))
setRefresh(false);
})
}
catch(error) {
console.log(error);
}
}
return <FlatList file={file} refreshing={refresh} onRefresh={onRefresh} />
}

Best way to fetch the data from API

I am making a simple react application in which I am in the need to display user list in select dropdown.
This user list comes from api.
So I am using Context API in my application and I have made a context and made the api call inside the context.
context.js
import React from "react";
import axios from "axios";
export const UserContext = React.createContext();
export function Provider({ children }) {
const getUsers = () => {
return axios.get(`https://randomuser.me/api/?results=10`).then((res) => {
return res;
});
};
return (
<UserContext.Provider value={{ usersList: getUsers() }}>
{children}
</UserContext.Provider>
);
}
users.js
-> Just including context where user data has been fetched and included react-select for dropdown.
-> Using useContext getting the promise value and inside useEffect hook getting the response and storing it in a state variable setUsers
-> In render method returning the select box values with the fetched users list as dropdown.
import React, { useContext, useEffect, useState } from "react";
import Select from "react-select";
import { UserContext } from "../context";
const Users = () => {
const { usersList } = useContext(UserContext);
const [users, setUsers] = useState([]);
const getUsers = () => {
usersList.then((users) => {
setUsers(users.data.results);
});
};
useEffect(() => {
getUsers();
}, []);
return (
<div>
<p> Below user list in select box is called from API </p>
<Select
value={""}
name="user"
options={users}
getOptionLabel={(option) => option.name.first}
getOptionValue={(option) => option.id.value}
className="basic-multi-select"
/>
</div>
);
};
export default Users;
Working example:
Query:
-> This works fine but in my real application this leads to multiple api calls.
-> I have checked in network tab and it has been called for at least 50 times and I feel that this will be a big issue regarding peroformance.
So I would like to know if there is a much better and standard way of implementing this in order to avoid memory leaks and multiple calls for an api fetch?
I am suspecting whether this line,
<UserContext.Provider value={{ usersList: getUsers() }}>
causing the real issue as I am calling getUsers() method with parathesis () but if I remove it the it doesn't get executed..
Please kindly help me and thanks in advance..
You can store the user list in an array, and have your components call getUsers on mount. Then just use users wherever you need
export function Provider({ children }) {
const [users, setUsers] = useState([]);
const getUsers = () => {
if (!users.length) {
axios.get(`https://randomuser.me/api/?results=10`).then((res) => {
setUsers(res.data.results);
});
}
};
return (
<UserContext.Provider value={{ usersList: users, getUsers }}>
{children}
</UserContext.Provider>
);
}
On User.js
const Users = () => {
const { usersList, getUsers } = useContext(UserContext);
useEffect(() => {
getUsers();
}, [getUsers]);
return (
<div>
<p> Below user list in select box is called from API </p>
<Select
value={""}
name="user"
options={users}
getOptionLabel={(option) => option.name.first}
getOptionValue={(option) => option.id.value}
className="basic-multi-select"
/>
</div>
);
};

Semantic UI React: Cannot take values from REST API for dropdown

I am trying to use the Dropdown element of Semantic UI React. It is meant to work with a REST API that allows to get a list of movies. React is configured to fetch data from the appropriate REST API application (this already works for other elements of the frontend).
I would like to get the list of movie names as options. Please have a look at the following JS snippet.
import React, { useState, useEffect } from "react";
import { Dropdown } from "semantic-ui-react";
export const MovieDropdown = () => {
const [movie, setMovie] = useState("");
const [movieOptions, setMovieOptions] = useState([]);
useEffect(() => {
fetch("/movies")
.then((response) => response.json())
.then((data) =>
setMovieOptions(
data.map((x) => {
return { key: x.name, text: x.name, value: x.name };
})
)
);
}, []);
return (
<Dropdown
placeholder="Select Movie"
search
selection
options={movieOptions}
onChange={(e) => setMovie(e.target.value)}
/>
);
};
export default MovieDropdown;
I could not figure it out from https://react.semantic-ui.com/modules/dropdown/#usage-remote.
Your code looks good. Change a small thing and it will work:
onChange={e => setMovie(e.target.value)} // you cannot use event in setState. furthermore checkout the second param of the onChange-Event
to
onChange={(e, {value}) => setMovie(value)}
checkout fixing-react-warning-synthetic-events-in-setstate
here's the full working code
import React, { useState, useEffect } from "react";
import { Dropdown } from "semantic-ui-react";
export const MovieDropdown = () => {
const [movie, setMovie] = useState("");
const [movieOptions, setMovieOptions] = useState([]);
useEffect(() => {
fetch("/movies")
.then((response) => response.json())
.then((data) =>
setMovieOptions(
data.map((x) => {
return { key: x.name, text: x.name, value: x.name };
})
)
);
}, []);
return (
<Dropdown
placeholder="Select Movie"
search
selection
options={movieOptions}
onChange={(e, {value}) => setMovie(value)}
/>
);
};
export default MovieDropdown;

React Asynchronous Fetching

Using React and React-Dom CDN 16
I am new to React and trying to build a dashboard component that takes the value of one of three buttons in a Buttons component and sends the value to a List component. The List component fetches data from an API and renders the results.
The feature works fine up until the data fetching, which it only does once the app is rendered the first time. I've logged that the state that's set by the Buttons component is making its way to the List component and the fetch action is updating dynamically correctly, but the fetching functionality isn't getting triggered when that state updates.
Here's the code.
const { useState, useEffect } = React
const App = props => {
return (
<div className="app-content">
<Dashboard />
</div>
);
};
const Dashboard = props => {
const [timespan, setTimespan] = useState('week');
const changeTime = time => setTimespan(time);
return(
<div>
<p>{timespan}</p> // this state updates when the buttons are clicked
<Buttons onUpdate={changeTime} />
<List timespan={timespan}/>
</div>
);
};
const Buttons = props => {
return (
<div>
<button onClick={props.onUpdate.bind( this, 'week' )}>
week
</button>
<button onClick={props.onUpdate.bind( this, 'month' )}>
month
</button>
<button onClick={props.onUpdate.bind( this, 'all' )}>
all
</button>
</div>
);
};
const List = props => {
const timespan = props.timespan;
const homepage = `${location.protocol}//${window.location.hostname}`;
const action = `${homepage}?fetchDataset=1&timespan=${timespan}`;
// if I console.log(action) here the URL is updated correctly
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [obj, setObj] = useState([]);
useEffect(() => {
fetch(action)
.then(res => res.json())
.then(
(result) => { // if I console.log(result) here I only get a response at initialization
setIsLoaded(true);
setObj(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, []);
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
// my API returns "timespan is: $timespan", but this is only ever "week" because that's the initial state of the timespan
{obj}
</div>
);
};
};
ReactDOM.render(
<App />,
document.getElementById('app')
);
I think I must be overlooking something very obvious because this seems like one of the core purposes of React, but it's hard to find documentation that is relevant with version 16 updates like function classes and hooks.
I really appreciate any help. Thanks!
you need to add timeSpan (or action) to your useEffect dependency array:
useEffect(() => {
fetch(action)
.then(res => res.json())
.then(
result => {
setIsLoaded(true);
setObj(result);
},
error => {
setIsLoaded(true);
setError(error);
}
);
}, [timeSpan]); // [action] will also solve this
This way the effect will know it needs to run every time the timeSpan prop changes.
By passing an empty dependency array you are telling the effect to only run once - when the component it mounted.

Categories

Resources