mutate function not working as i expected, when sharing same state with other components
expect:
every mutate call by clicking button, re-fetch original data, so i can find new post.json request on networkTab
working: but, every mutate call, not fetch new data. i couldn't find post.json on networkTab
if i remove Item.js file, it works as i expected.(every mutate-call, every re-fetch)
why this happening?
//App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import useSWR from 'swr'
import ItemList from './ItemList';
function App() {
React.useEffect(()=>{
console.log('rerender')
})
const fetcher = async(urlKey) => {
const url = 'https://jsonplaceholder.typicode.com/posts';
const response = await fetch(url);
const result = await response.json();
return result
}
const {data,error,mutate} = useSWR('/get/posts',fetcher);
const updateFetch = () => {
mutate({},true);
}
return (
<div className="App">
<ItemList/>
<button onClick={updateFetch}>reFresh</button>
</div>
);
}
export default App;
//ItemList.js
import React from 'react'
import useSWR from 'swr';
function ItemList() {
const {data,error} = useSWR('/get/posts');
return null
}
export default ItemList
According to docs:
broadcast a revalidation message globally to other SWR hooks using the same key by calling mutate(key).
i.e You have to tell mutate which Api data you have to fetch again in your case. It would be like this:
mutate('/get/posts',true)
I have created this sandbox for reference: https://codesandbox.io/embed/reverent-cloud-fhm2w
Related
Here I am getting my data from child component and trying to add it into existing array and also I am trying to display it in console using map but the moment I try to to do so I get nothing in console:
import "./App.css";
import Home from "./Components/Home";
import {useState} from 'react';
let App = () => {
let DataList = ["Apple","Banana"];
const newList = (data)=>{
DataList = [...DataList,data];
}
return (
<div>
<Home newList = {newList}/>
{ DataList.map((val)=>(
console.log(val)
))
}
</div>
)
};
export default App;
You need to use React hooks to make it work, then only your component will rerender
import "./App.css";
import Home from "./Components/Home";
import {useState} from 'react';
let App = () => {
const [DataList, setDataList] = useState(["Apple","Banana"]);
const newList = (data)=>{
let temp = [...DataList,data];
setDataList(temp);
}
return (
<div>
<Home newList = {newList}/>
{ DataList.map((val)=>(
console.log(val)
))
}
</div>
)
};
export default App;
You imported this for a reason, use it:
import {useState} from 'react';
React won't detect changes to any random variable you declare. So there's no reason for it to re-render the component in the code you have.
State values are fundamental to React. It's how you persist data across renders, and it's how React knows to re-render any given component. Store your data in state:
const [dataList, setDataList] = useState(["Apple","Banana"]);
And use that setter function to update the state:
const newList = (data)=>{
setDataList([...dataList, data]);
};
When React sees that state was updated, it will queue a re-render of the component (in this case re-invoking the App function internally to the framework) so the new state can be used.
I hava a component called videoRow i try to render this component using dummy values now i get data from a useEffect Hook i have to use that data to render my component but when i try to do so it dont show anything. I even try console log to check weather i get my data or not it print my data on console means my useEffect is working But when i try this data on my videoRow component it not show anything
import React, { useState, useEffect } from "react";
import "../css/searchPage.css";
import TuneSharpIcon from "#mui/icons-material/TuneSharp";
import ChannelRow from "./ChannelRow";
import VideoRow from "./VideoRow";
import { selectInput } from "../features/inputSlice";
import { useSelector } from "react-redux";
import Axios from "axios";
function SearchPage() {
const getQuery = useSelector(selectInput);
const API_URL = `https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=4&key=APIKEY&type=video&q=${getQuery.input}`;
const [data, setData] = useState([]);
useEffect(() => {
async function fetchData() {
let request = await Axios.get(API_URL);
setData(request);
}
fetchData();
}, [API_URL]);
console.log(data);
return (
<div className="searchPage">
<div className="filter">
<TuneSharpIcon></TuneSharpIcon>
<h2>FILTERS</h2>
</div>
<hr></hr>
<ChannelRow
image="https://images.indianexpress.com/2022/01/Republic-Day_1200_AP2022.jpg"
channelName="Dummy"
verified
subs="670k"
noOfVideos={567}
desc="You can find awesome programming lessons here! Also, expect programming tips and tricks that will take your coding skills to the ..."
></ChannelRow>
<hr></hr>
{data?.data?.items?.forEach((item) => {
console.log(item.snippet.title);
console.log(item?.snippet.thumbnails.high.url)
console.log(item?.snippet.publishedAt)
console.log(item?.snippet.description)
console.log(item?.snippet.channelTitle)
return(<VideoRow
image={item?.snippet.thumbnails.high.url}
channelName={item?.channelTitle}
timestamp={item?.snippet.publishedAt}
title={item?.snippet.title}
desc={item?.snippet.description}
views="1.4M"
subs="1.4M"
></VideoRow>)
})}
</div>
);
}
export default SearchPage;
Change data?.data?.items?.forEach to data?.data?.items?.map. forEach returns nothing. So, even if you return the component from the callback, forEach will just ignore it. But, map will return all transformed results as an array.
You can read more about lists in react here.
There's WarriorPage component which use context where is data I want to render. After page refresh, firstly I got an empty array from the context and only after a while I got array with my data. That causes error because I'm destructuring object from that array(which is empty in the start). Any sugestions?
WarriorPage
import React, { useContext } from 'react';
import { useParams } from 'react-router-dom';
import AllWarriorsContext from '../../contexts/AllWariorsContext';
export default function WarriorPage() {
let { identy } = useParams();
const { warriorsData } = useContext(AllWarriorsContext);
const {number, name, skill, description} = warriorsData[identy]; // got undefined here after page reload
return(...);
}
In Parent component
import React, { useEffect, useState, useContext } from 'react';
import AllWarriorsContext from '../../contexts/AllWariorsContext';
import WarriorPage from '../WarriorPage/WarriorPage';
export default function Parent() {
const [myWarriorsListContext, setMyWarriorsListContext] = useState([]);
useEffect( () => {
setMyWarriorsListContext(JSON.parse(localStorage.getItem('myWarriorsList')) || []);
},[]);
return(
<AllWarriorsContext.Provider value={{
warriorsData: allWarriorsData
}}>
<WarriorPage />
</AllWarriorsContext>
);
}
1. Static object
To create context based on a static object, I use this code:
import React, { createContext } from 'react';
const user = {uid: '27384nfaskjnb2i4uf'};
const UserContext = createContext(user);
export default UserContext;
This code works fine.
2. Dynamic object
But if I need to create context after fetching data, I use this code:
import React, { createContext } from 'react';
const UserContext = () => {
// Let's suppose I fetched data and got user object
const user = {uid: '18937829FJnfmJjoE'};
// Creating context
const context = createContext(user);
// Returning context
return context;
}
export default UserContext;
Problem
When I debugg option 1, console.log(user) returns the object. Instead, option 2, console.log(user) returns undefined. What I'm missing?
import React, { useEffect, useState, useContext } from 'react';
import UserContext from './UserContext';
const ProjectSelector = (props) => {
const user = useContext(UserContext);
console.log(user);
return(...);
}
export default App;
one thing i would suggest is move this logic to a react component itself.
anhow you need to use a Provider in which you will set value to be the value consumers need to consume.useEffect is greatway to do asynchronous updates, like your requirment.
so , use a state variable as value of provider.in useEffect you fetch the data and update the state variable which in turn will update context value.
following is the code
UserContext.js
import { createContext } from "react";
const UserContext = createContext();
export default UserContext;
App.js
export default function App() {
const [user, setUser] = useState();
useEffect(() => {
console.log("here");
fetch("https://reqres.in/api/users/2")
.then(response => {
return response.json();
})
.then(data => {
setUser(data);
});
}, []);
return (
<div className="App">
<UserContext.Provider value={user}>
<DummyConsumer />
</UserContext.Provider>
</div>
);
}
DummyConsumer.js
import React, { useContext } from "react";
import UserContext from "./UserContext";
const DummyConsumer = () => {
const dataFromContext = useContext(UserContext);
return <div>{JSON.stringify(dataFromContext)}</div>;
};
export default DummyConsumer;
demo:anychronus context value providing
I'm new reactjs
I'm trying to save data that I got from server like object(array) but I can't.
at render() function, what should I do to save data, I don't wanna display, just save to users (array) or something? I think that I should use "map" but I don't know how to do.
Next, I wanna save users to model.data like this. help me.
Since you just started using react, try using React Hooks instead of class style components. It's the recommended way.
If you just want to store the data without displaying anything you need somekind of a encapsulated/shared state. For example redux or context can help you with that. Since context is in-built and easier to use, here is an example:
First create a context
users-context.js
import React from "react";
export const UsersContext= React.createContext();
Now create a custom hook to store your state.
useUsers.js
import React, {useState, useEffect} from "react";
export const useUsers = () => {
const [users, setUsers] = useState([]);
const getUsers = () =>{
//your fetch
}
useEffect(()=>{ //equivalent to componentDidMount
getUsers();
}, [])
return {users, setUsers}
}
Then provide the context so every component in your app has access to that context.
App.jsx
import {UsersContext} from "./UsersContext";
const App = () => {
const contextValue = useUsers();
return (
<div className={'App'}>
<UsersContext.Provider value={contextValue}>
<Main/>
</UsersContext.Provider>
</div>
);
};
export default App;
If you want to use the state in a component, e.g. a profile page do this:
profile-page.jsx
import React, {useContext} from "react";
import {UsersContext} from "./UsersContext";
const ProfilePage = () => {
const {users} = useContext(UsersContext);
// now you can use it like
console.log(users)
return (...)
}
import { UsersContext } from './Components/usersData/users-context';
const getUsers = () => {
const {users} = UsersContext(UsersContext);
console.log(users);
return users;
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data:[]
}
data.push(getUsers);`
}
}