I have this problem.
I have defined two components. One for showing data, another one for searching. They are not connected together, but works independly. I use react-query for getting data from API.
Searchbox:
const SearchBox = () => {
const { data, status } = useQuery(['planets', searchTerm], () => fetchSearchingResults('planets', searchTerm), { enabled: Boolean(searchTerm)});
...
PlanetsList
const PlanetsList = () => {
const { data, status } = useQuery('planets', () => fetchResourceData('planets'));
**I change query data in SearchBox by searching and handling local state, it works. But I need call re-render of PlanetsList with data from SearchBox query result. How to do it? Is it possible **
You will need to call the same exact query in PlanetList.
Simple rerender won't help because useQuery(['planets', searchTerm]) and useQuery('planets') are completly different cache.
You could try to wrap your planets query in function if both queries gives the same type of result.
const usePlanetsQuery (searchTerm?: string) => {
return useQuery(['planets', searchTerm], () => searchTerm ? fetchSearchingResults('planets', searchTerm) : fetchResourceData('planets'));
}
const SearchBox = () => {
const searchTerm = selectSearchTempFromContextOrStateManageOrProps();
const { data, status } = usePlanetsQuery(searchTerm);
const PlanetsList = ({searchTerm}: {searchTerm: string}) => {
const { data, status } = usePlanetsQuery(searchTerm);
}
}
It will synchronize your results between SearchBox and PlanetsList
Related
I want to update this "holidays" array, by calling function only when countryAttr state changes.
export default function Home() {
const [countryAttribute, setCountryAttribute] = React.useState(null)
const getHolidays = () => {
const CALENDAR_REGION = `en.${countryAttribute.attr}`;
const calendar_url = `${BASE_CALENDAR_URL}/${CALENDAR_REGION}%23${BASE_CALENDAR_ID_FOR_PUBLIC_HOLIDAY}/events?key=${mykey}`
let holidays = new Array()
return axios.get(calendar_url)
.then(res => {res.data.items.map(
val => {
holidays = [...holidays, {holidayName: val.summary}
]
})
})
}
return (...)
}
Unfortunately, now, that pre-render any time when this component is loaded, and I want to write this array somewhere until demand state will be changed.
I want to make hook to get data from Snapshot to display proposals. I use graphql-request library to get data. I want to get this data in component for example: const { data } = useSnapshotProposalsQuery(). How can i do this? For now i can only get const data = useSnapshotProposalsQuery() and when i am console.log(data) i get Promise{<opening>}. My code:
import { gql, request } from 'graphql-request';
export const useSnapshotProposals = gql`
query Proposals {
proposals(
first: 20
skip: 0
where: { space_in: ["example.eth"] }
orderBy: "created"
orderDirection: desc
) {
id
title
body
choices
start
end
snapshot
state
author
space {
id
name
}
}
}
`;
export const useSnapshotProposalsQuery = () => {
return request('https://hub.snapshot.org/graphql', useSnapshotProposals).then((data) => data);
};
You create a custom hook. and that hook returns a state. when sideeffect inside that hook happens, the state is updated and your outer component gets re-rendered. (react docs)
export const useSnapshotProposalsQuery = () => {
const [myData, setMyData] = useState(null);
useEffect(()=>{
request('https://hub.snapshot.org/graphql', useSnapshotProposals).then((data) => {setMyData(data)});
}, []); // run only one time
return myData;
};
in outer component:
function ABCcomponent () {
const myData = useSnapshotProposalsQuery(); // it will be null at first, but will be filled with data later.
return (
/*ui that uses myData */
)
}
I have a React Native functional component.
I'm using useEffect to fetch some data from AsycStorage and set it to local state. However, before rendering, I want to do some processing/calculations on this data before I can render it on screen. Where should I be doing this calculation?
My screen looks as follows:
const BasicScreen = ({ data, getPosts }) => {
const [myItems, setItems] = useState([]);
const checkForItems = () => {
var storageItems = AsyncStorage.getItem("MyItems").then((item) => {
if (item) {
return JSON.parse(item);
}
});
setItems(storageItems);
};
useEffect(() => {
async function getItems() {
await checkForItems(); // calling function to get data from storage
}
getItems(); // Local Storage
getPosts(); // Store action
}, []);
return (
<View>
<>
<Text>{JSON.stringify(processedItemsA)}</Text>
<Text>{JSON.stringify(processedItemsB)}</Text>
</>
</View>
);
}
export default BasicScreen;
As you can see, I check for items in AsyncStorage and set that data to local state myItems.
I want to do some mathematical calculations and some conditional logic, for example, separate the data of myItems into two separate categories, and then render that on screen. Something like processedItemsA and processedItemsB. Where should I be doing this processing of data?
processedItemsA = myItems => {
// Some logic
}
processedItemsB = myItems => {
// Some logic
}
I'm not sure about where this logic should go.
Note that this processing is required because apart from storage, I also get some data from redux store, and then process it along with that data.
This way you can achieve this
const [processedItemsA, setProcessedItemsA] = useState({});
const [processedItemsB, setProcessedItemsB] = useState({});
doProcessedItemsA = myItems => {
...
setProcessedItemsA({...data}); // set data after process Item A
}
doProcessedItemsB = myItems => {
...
setProcessedItemsB({...data}); // set data after process Item B
}
const checkForItems = () => {
var storageItems = AsyncStorage.getItem("MyItems").then((item) => {
if (item) {
const parsedItem = JSON.parse(item);
doProcessedItemsA(parsedItem);
doProcessedItemsB(parsedItem);
}
});
// setItems(storageItems); <-- No need to set here -->
};
I call multiple graphql query using useQuery. And it's shows error like
Too many re-renders. React limits the number of renders to prevent an infinite loop.
I know why it came but i don't know how to prevent from this error. This is Functional components
my code here
const [categoryList, updateCategoryList] = useState([]);
const [payeeList, updatePayeeList] = useState([]);
if (data) {
const categories = (data.categories as unknown) as Category[];
if (
!isEqual(categoryList, categories) ||
categoryList.length !== categories.length
) {
updateCategoryList([...categories]);
}
}
if (isEmpty(payeeList)) {
const { loading, data } = useQuery(payeesQuery);
if (data) {
const payees = (data.payees as unknown) as Payee[];
if (!isEqual(payeeList, payees) || payeeList.length !== payees.length) {
updateCategoryList([...payees]);
}
}
}
Sorry guys I noob for react.
for eg you can use like this
const ExampleComponent = () => {
const { loading:payeesLoading, data:payeesData } = useQuery(payeesQuery);
const { loading:secondLoading, data:secondData } = useQuery(secondQuery);
useEffect(() => { //effect hook for first query
} ,[payeesData] )
useEffect(() => { //effect hook for second query
} ,[secondData] )
return (<div>
your contents
</div>)
}
like this you can write multiple querys in a single component.
In my React-App (create-react-app) I use a selector (created with reselect) to compute derived data from stored data.The Problem is, the selector takes a long time to compute. I would like to show a spinner (or a message) on the user interface. But each time the selector is recomputed the ui freezes.
I read a lot of stuff (Web Worker, requestIdleCallback, requestAnimationFrame) and try to make my own React hook but I am stuck. I cannot use the selector in callbacks.
The searched result is simply to get the ui refreshed before the selector is recomputed.
That's my solution. I don't know if it's "good" or if it breaks some rules of react or reselect, but it works. Maybe you can assess that?The code is simplified to improve readability.
The idea is, the selector returns a Promise and I call requestAnimationFrame before computing the data to get a chance to refresh the ui.
selector.js:
const dataSelector = state => state.data;
export const getDataComputedPromise = createSelector([dataSelector], (data) => {
const compute = function () {
return new Promise((resolve) => {
// heavy computing stuff
resolve(computedData);
});
};
return new Promise((resolve) => {
let start = null;
let requestId = null;
function step (timestamp) {
if (!start) {
start = timestamp;
window.cancelAnimationFrame(requestId);
requestId = window.requestAnimationFrame(step);
return;
};
compute().then(freeResources => {
window.cancelAnimationFrame(requestId);
resolve(freeResources);
});
}
requestId = window.requestAnimationFrame(step);
});
});
myPage.js
const MyPage = ({ someProps }) => {
...
const dataComputedPromise = useSelector(getDataComputedPromise);
const [dataComputed, setDataComputed] = useState([]);
const [computeSelector, setComputeSelector] = useState(false);
useEffect(() => {
setComputeSelector(true);
}, [data]);
useEffect(() => {
dataComputedPromise.then(dataComputed => {
setDataComputed(dataComputed);
setComputeSelector(false);
});
}, [dataComputedPromise]);
...
return <div>
<Loader active={compueSelector}>Computing data...</Loader>
</div>;
};
export default MyPage;