Can't pass data from getStaticProps to the NextPage component - reactjs

I recieve properly the datas desired with getStaticProps. But I can't understand why they are not passed to the BlogPrivate component. I have exactly the same structure in another file, and it works just well...
articlesStrapi is always undefined
Here is the code
import React, { useEffect, useState } from 'react';
import { GetStaticProps, NextPage } from 'next';
import { ArticleStrapi } from '../../#types/next';
import Article from './article';
type articlesStrapiProps = { articlesStrapi: ArticleStrapi[] };
const BlogPrivate: NextPage<articlesStrapiProps> = ({ articlesStrapi }) => {
console.log(articlesStrapi); ==> return undefined
return (
<div style={{ display: 'flex', flexDirection: 'row' }}>
//////
</div>
);
};
export const getStaticProps: GetStaticProps<{ articlesFromStrapi: ArticleStrapi[] }> = async () => {
const res = await fetch(`${process.env.NEXT_PUBLIC_BACKEND}api/articles`);
const { data } = await res.json();
const articlesFromStrapi: ArticleStrapi[] = data;
return !articlesFromStrapi
? { notFound: true }
: {
props: { articlesFromStrapi },
revalidate: 10 // In seconds
};
};
export default BlogPrivate;
there is the result of a console log of the articlesFromStrapi in the getStaticProps :
[
{
id: 1,
attributes: {
title: 'Article 1dgdrgdr',
createdAt: '2022-11-22T13:28:16.243Z',
updatedAt: '2022-11-22T18:02:50.096Z',
publishedAt: '2022-11-22T13:49:16.161Z',
content: 'dfdsf sdf ds '
}
},
{
id: 6,
attributes: {
title: 'fdsfdsf',
createdAt: '2022-11-22T18:01:47.759Z',
updatedAt: '2022-11-22T18:01:48.440Z',
publishedAt: '2022-11-22T18:01:48.438Z',
content: 'dsf sdf dsf dsf dsf dsf dsf dsf '
}
}
]
And here are my interfaces :
export interface ArticleStrapi {
id: string;
attributes: Article;
}
export interface Article {
title: string;
content: string;
createdAt: string;
publishedAt: string;
updatedAt: string;
}
Let me know if you see any mistake I could do...
Thanks :)

Well your data names are not equivalent.
The prop that the component gets is articlesStrapi and the prop that you're returning from getStaticProps is articlesFromStrapi.
Here is the correct code:
const BlogPrivate: NextPage<articlesStrapiProps> = ({ articlesFromStrapi }) => {
console.log(articlesFromStrapi); ==> return undefined
return (
<div style={{ display: 'flex', flexDirection: 'row' }}>
//////
</div>
);
}
Or by changing the prop name in getStaticProps:
export const getStaticProps: GetStaticProps<{ articlesFromStrapi: ArticleStrapi[] }> = async () => {
const res = await fetch(`${process.env.NEXT_PUBLIC_BACKEND}api/articles`);
const { data } = await res.json();
const articlesFromStrapi: ArticleStrapi[] = data;
return !articlesFromStrapi
? { notFound: true }
: {
props: { articlesStrapi: articlesFromStrapi },
revalidate: 10 // In seconds
};
};

Related

useRecuder + typescript error Argument of type '(type, action) => { state: (...}' is not assignable to parameter of type 'ReducerWithoutAction<any>'

Im trying to learn typescript so i decided to do a simple shopping cart app
GitHub repository: https://github.com/CsarGomez/shopping-cart-reducers-tx
im getting the following error:
No overload matches this call.
Overload 1 of 5, '(reducer: ReducerWithoutAction, initializerArg: any, initializer?: undefined): [any, DispatchWithoutAction]', gave the following error.
Argument of type '(state: ShoppingInitialState, action: shoppingReducer) => { cart: (ProductInterface | undefined)[]; products: ProductInterface[]; }' is not assignable to parameter of type 'ReducerWithoutAction'.
Overload 2 of 5, '(reducer: (state: ShoppingInitialState, action: shoppingReducer) => { cart: (ProductInterface | undefined)[]; products: ProductInterface[]; }, initialState: never, initializer?: undefined): [...]', gave the following error.
Argument of type 'ShoppingInitialState' is not assignable to parameter of type 'never'
and i don't know what im doing wrong, it will be really appreciate if someone can explain me where the issue is, and why its happen
here's more detail:
i have a model folder that contains all the interfaces:
shopping.interface.ts
export enum ActionsTypes {
ADD_TO_CART = 'ADD_TO_CART',
REMOVE_ONE_FROM_CART = 'REMOVE_ONE_FROM_CART',
REMOVE_ALL_FROM_CART = 'REMOVE_ALL_FROM_CART',
CLEAN_CART = 'CLEAN_CART',
}
export interface shoppingReducer {
type: ActionsTypes;
payload: number;
}
export interface ShoppingInitialState {
products: Array<ProductInterface>;
cart: Array<ProductInterface>;
}
interface ProductInterface {
id: number;
image: string;
name: string;
price: number;
}
i have a folder called reducers and inside my reducer:
shopping.reducer.ts
import { ACTIONS } from '#/actions/shopping.actions';
import {
ShoppingInitialState,
shoppingReducer,
} from '#/models/shopping.interface';
export const shoppingInitialState: ShoppingInitialState = {
products: [
{
id: 1,
image: 'https://placeimg.com/200/200/tech/1',
name: 'Product 1',
price: 100,
},
{
id: 2,
image: 'https://placeimg.com/200/200/tech/2',
name: 'Product 2',
price: 200,
},
{
id: 3,
image: 'https://placeimg.com/200/200/tech/3',
name: 'Product 3',
price: 100,
},
{
id: 4,
image: 'https://placeimg.com/200/200/tech/4',
name: 'Product 4',
price: 400,
},
{
id: 5,
image: 'https://placeimg.com/200/200/tech/5',
name: 'Product 5',
price: 100,
},
{
id: 6,
image: 'https://placeimg.com/200/200/tech/6',
name: 'Product 6',
price: 600,
},
],
cart: [],
};
export function shoppingReducer(
state: ShoppingInitialState,
action: shoppingReducer
) {
const { type, payload } = action;
switch (type) {
case ACTIONS.ADD_TO_CART: {
let addCartItem = state.products.find(
(product) => product.id === payload
);
return {
...state,
cart: [...state.cart, addCartItem],
};
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.CLEAN_CART: {
}
default:
return state;
}
}
a folder called components with
Cart.tsx:
import { useReducer } from 'react';
import {
shoppingInitialState,
shoppingReducer,
} from '#/reducers/shopping.reducer';
const Cart: React.FC = () => {
const deleteFromCart = () => {};
const clearCart = (id: number) => {
console.log(id);
};
const [state, dispatch] = useReducer(shoppingReducer, shoppingInitialState);
const { cart } = state;
return (
<div className='cart'>
<button className='btn-primary'>Clean Cart</button>
{cart.length === 0 ? (
<div className='center'>No products yet</div>
) : (
cart.map((item) => (
<div key={item.id} className='cart__card'>
<div className='cart__details'>
<p>{item.name}</p>
<p>USD$ {item.price}</p>
</div>
<button>Remove from Cart</button>
</div>
))
)}
</div>
);
};
export default Cart;
Products.tsx:
import { useReducer } from 'react';
import {
shoppingInitialState,
shoppingReducer,
} from '#/reducers/shopping.reducer';
import { ActionsTypes } from '#/models/shopping.interface';
const Products: React.FC = () => {
const addToCart = (id: number) => {
dispatch({ type: ActionsTypes.ADD_TO_CART, payload: id });
console.log(id);
};
const deleteFromCart = () => {};
const clearCart = () => {};
const [state, dispatch] = useReducer(shoppingReducer, shoppingInitialState);
const { products } = state;
return (
<div className='products'>
{products.map((product) => (
<div key={product.id} className='product__card'>
<img src={product.image} alt='product image' />
<div className='product__details'>
<p>{product.name}</p>
<p>USD$ {product.price}</p>
</div>
<button onClick={() => addToCart(product.id)} className='btn-primary'>
Add to Cart
</button>
</div>
))}
</div>
);
};
export default Products;
and finally the app:
import '#styles/reset.scss';
import '#styles/App.scss';
import Products from '#/components/Products';
import Cart from '#/components/Cart';
function App() {
return (
<main>
<section>
<h2>Shopping Cart</h2>
<hr />
<Products />
</section>
<section className='order'>
<h2>Order Summary</h2>
<hr />
<Cart />
</section>
</main>
);
}
export default App;
im getting multiple errors a soon as i try to add an item into cart state using the reducers, more explicit when i add this line in shopping.reducers.ts
case ACTIONS.ADD_TO_CART: {
let addCartItem = state.products.find(
(product) => product.id === payload
);
return {
...state,
***cart: [...state.cart, addCartItem],***
};
the return type of your "shoppingReducer" dont have the same type that initialState.
///shopping.interface.ts
// types of actions in the reducer
export enum ActionsTypes {
ADD_TO_CART = 'ADD_TO_CART',
REMOVE_ONE_FROM_CART = 'REMOVE_ONE_FROM_CART',
REMOVE_ALL_FROM_CART = 'REMOVE_ALL_FROM_CART',
CLEAN_CART = 'CLEAN_CART',
}
export type CartActionType = {
type: ActionsTypes,
payload: number
}
export type IshoppingReducer = {
type: ActionsTypes;
payload: number;
}
export type State = {
cart:Array<any>
products: Array<any>;
}
export interface shoppingReducer {
type: ActionsTypes;
payload: number;
}
export interface ShoppingInitialState {
products: Array<ProductInterface>;
cart: Array<ProductInterface>;
}
interface ProductInterface {
id: number;
image: string;
name: string;
price: number;
}
/// shopping.reducer.ts
import {
CartActionType,
ShoppingInitialState,
shoppingReducer,
State,
} from '#/models/shopping.interface';
export const shoppingInitialState: ShoppingInitialState = {
products: [{
id: 1,
image: 'https://placeimg.com/200/200/tech/1',
name: 'Product 1',
price: 100,
},]
cart: [],
};
export function shoppingReducer(
state: ShoppingInitialState,
action: CartActionType
):State {
const { type, payload } = action;
switch (type) {
case ACTIONS.ADD_TO_CART: {
let addCartItem = state.products.find(
(product) => product.id === payload
);
return {
...state,
cart: [...state.cart, addCartItem],
};
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.CLEAN_CART: {
}
default:
return state;
}
}
//Products.tsx
import { useReducer } from 'react';
import {
shoppingInitialState,
shoppingReducer,
} from '#/reducers/shopping.reducer';
import { ActionsTypes } from '#/models/shopping.interface';
const Products: React.FC = () => {
const [state, cartDispatch] = useReducer(shoppingReducer,shoppingInitialState);
const addToCart = async(id: number) => {
cartDispatch({ type: ActionsTypes.ADD_TO_CART, payload: id });
console.log(id);
};
const deleteFromCart = () => {};
const clearCart = () => {};
const { products } = state;
return (
<div className='products'>
{products.map((product:any) => (
<div key={product.id} className='product__card'>
<img src={product.image} alt='product image' />
<div className='product__details'>
<p>{product.name}</p>
<p>USD$ {product.price}</p>
</div>
<button onClick={() => addToCart(product.id)} className='btn-primary'>
Add to Cart
</button>
</div>
))}
</div>
);
};
export default Products;
Try changing this in shopping.reducer.ts:
export function shoppingReducer(
state = ShoppingInitialState, // Here you need to assign a value, so = instead of :
action: shoppingReducer
) {
const { type, payload } = action;
switch (type) {
case ACTIONS.ADD_TO_CART: {
let addCartItem = state.products.find(
(product) => product.id === payload
);
return {
...state,
cart: [...state.cart, addCartItem],
};
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.REMOVE_ONE_FROM_CART: {
}
case ACTIONS.CLEAN_CART: {
}
default:
return state;
}
}

React Recoil values not returning corresponding JSON string

The function
export function Text({ text }) {
const dictionary = useDefaultDictionary();
return <span>{dictionary[text]}</span>;
}
Works as expected, I assumed as much that I could use useDefaultDictionary.setResultLang to get the corresponding value from my JSON to complete the call, even using another const defined by that set of values did not work
export const currentGenresQuery = selector({
key: 'currentGenresQuery',
get: async () => {
const response = await fetch(`${API_URL}genre/movie/list?api_key=${TMDB_API_KEY}&language=${useDefaultDictionary.setResultLang}`);
const data = await response.json();
return data.genres;
},
set: genresAtom,
});
but when I console.log(useDefaultDictionary) I get the following in the console
() => {
_s();
return (0,recoil__WEBPACK_IMPORTED_MODULE_1__.useRecoilValue)(dictionaryListAtom);
} set
Earlier I tried calling the atom directly, calling a const that called the useRecoilValue, calling the selector, calling a selectorFamily, I cannot seem to get this to return as I need it to which should be ah language and country code for the API call.
Please let me know if you have any ideas or need to see more of the code, but I am pretty sure this should be good to help figure what I am trying to do
import React, { useState, useEffect } from 'react';
import {
atom,
useRecoilState,
selector,
selectorFamily,
useRecoilValue,
useRecoilCallback,
} from 'recoil';
import { MenuItem, Menu, Button } from '#mui/material';
import ButtonGroup from '#mui/material/ButtonGroup';
import { styled } from '#mui/material/styles';
import PopupState, { bindTrigger, bindMenu } from 'material-ui-popup-state';
import { languageOptions, dictionaries } from '../components/languages/index';
import { TMDB_API_KEY } from '../apis/tmdb/key';
import youtube from '../apis/youtube/youtube';
/**
*
* Create a list of atoms to be used in the app.
* These atoms are used to store the state of the app.
* Core is the core of the app and where the atoms are created.
*
* We need the following atoms:
* defaultLanguage: string
* userLanguage: string
* dictionary: object
* genres: array
* currenGenreIdState: string
* movies: array
* movieId: string
* movieTitle: string
* movieOverview: string
* movieTrailer: string
* moviePoster: string
* movieReleaseDate: string
* movieGenres: array
* movieRating: string
* movieRuntime: string
* userGenres: array
* userFavorites: array
* userFavoritesId: string
*
* Add more atoms as needed.
*
*/
const StyledButtonGroup = styled(ButtonGroup)({
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
color: 'white',
});
const StyledButton = styled(Button)({
color: 'white',
backgroundColor: '#171515',
borderRadius: '25%',
border: '1px solid #171515',
fontSize: '1.2rem',
padding: '0.5rem',
margin: '0.5rem',
'&:hover': {
backgroundColor: '#716f6f',
},
});
const API_URL = 'https://api.themoviedb.org/3/';
// setting up local storage state persistence
export const localStorageEffect = key => ({setSelf, onSet}) => {
const savedValue = localStorage.getItem(key);
if (savedValue !== null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue, _, isReset) => {
isReset
? localStorage.removeItem(key)
: localStorage.setItem(key, JSON.stringify(newValue));
});
};
// export const tmdbApiUrlAtom = atom({
// key: 'tmdbApiUrlAtom',
export const defaultLanguageAtom = atom({
key: 'defaultLanguage',
default: 'enUS',
effects: [
localStorageEffect('rcml-lang'),
],
});
export const dictionaryListAtom = atom({
key: 'dictionaryList',
default: dictionaries.enUS,
effects: [
localStorageEffect('dictionaryList'),
],
});
export const useDefaultDictionary = () => {
return useRecoilValue(dictionaryListAtom);
}
export const checkDictionary = selector({
key: 'checkDictionary',
get: ({get}) => get(dictionaryListAtom),
});
export const dictionaryChange = selector({
key: 'dictionaryChange',
get: ({ get }) => ({...get(dictionaryListAtom) }),
set: ({ set }, value) => set(dictionaryListAtom, value),
});
export const currentLanguageQuery = selector({
key: 'currentLanguageQuery',
get: ({ get }) => get(dictionaryListAtom),
});
export function SetAppLanguage() {
const [dictionary, setDictionary] = useRecoilState(dictionaryChange);
const [language, setLanguage] = useState(languageOptions.enUS);
const handleChange = (event) => {
setLanguage(event.target.value);
setDictionary(dictionaries[event.target.value]);
}
return (
<StyledButtonGroup
value={language}
key={dictionary}
>
{Object.entries(languageOptions).map(([id, name]) => (
<StyledButton key={id} value={id} sx={{fontFamily:'Bebas Neue', color:'#E50914'}} onClick={handleChange}>{name}</StyledButton>
))}
</StyledButtonGroup>
);
};
// dictionary change callback
export function Text({ text }) {
const dictionary = useDefaultDictionary();
return <span>{dictionary[text]}</span>;
}
export const dictionaryAtom = atom({
key: 'dictionary',
default: [],
});
export const genresAtom = atom({
key: 'genres',
default: ['enUS'],
});
export const currentGenreIdState = atom({
key: 'CurrentGenreIdState',
default: '',
});
export const moviesAtom = atom({
key: 'movies',
default: [],
});
export const movieIdAtom = atom({
key: 'movieId',
default: '',
});
export const movieTitleAtom = atom({
key: 'movieTitle',
default: '',
});
export const movieOverviewAtom = atom({
key: 'movieOverview',
default: '',
});
export const movieTrailerAtom = atom({
key: 'movieTrailer',
default: '',
});
export const moviePosterAtom = atom({
key: 'moviePoster',
default: '',
});
export const movieReleaseDateAtom = atom({
key: 'movieReleaseDate',
default: '',
});
export const movieGenresAtom = atom({
key: 'movieGenres',
default: [],
});
export const movieRatingAtom = atom({
key: 'movieRating',
default: '',
});
export const movieRuntimeAtom = atom({
key: 'movieRuntime',
default: '',
});
export const userGenresAtom = atom({
key: 'userGenres',
default: [],
});
export const userFavoritesAtom = atom({
key: 'userFavorites',
default: [],
});
export const userFavoritesIdAtom = atom({
key: 'userFavoritesId',
default: '',
});
// state containing the current language code from the json file
// selectors, selector families, & queries
// current genres query and movie query
export const currentGenresQuery = selector({
key: 'currentGenresQuery',
get: async () => {
const response = await fetch(`${API_URL}genre/movie/list?api_key=${TMDB_API_KEY}&language=${useDefaultDictionary.setResultLang}`);
const data = await response.json();
return data.genres;
},
set: genresAtom,
});
export const genreInfoQuery = selectorFamily({
key: 'genreInfoQuery',
get: async (id) => {
const response = await fetch(`${API_URL}discover/movie?api_key=${TMDB_API_KEY}&language=${useDefaultDictionary.setResultLang}&with_genres=${id}`);
const data = await response.json();
return data;
}
});
export function CurrentGenres() {
const genres = useRecoilValue(currentGenresQuery);
console.log(useDefaultDictionary + ' set') // this is the language set by the user
const changeGenre = useRecoilCallback(
({snapshot, set}) => genreId => {
snapshot.getLoadable(genreInfoQuery(genreId))
set(currentGenreIdState, genreId)
}
)
const doBothThings = (popup, genre) => {
popup.close(genre.id)
changeGenre(genre.id)
}
return (
<PopupState variant="popover" popupId="demo-popup-menu">
{(popup) => (
<React.Fragment>
<Button variant="contained" {...bindTrigger(popup)}>
<Text text="sortBy" />
</Button>
<Menu {...bindMenu(popup)}>
{genres?.map((genre) =>(
<MenuItem
key={genre.id}
value={genre.id}
onClick={() => doBothThings(popup, genre)}
>
{genre.name}
</MenuItem>
))}
</Menu>
</React.Fragment>
)}
</PopupState>
)
};

NextJs nested dynamic routes based on API

I am stuck with Nextjs : I need to create nested dynamic routes based on my (local) data.
Here are the routes that I would like to create :
.../cars/ -> displays all the categories (sedan, suv, 4x4)
.../cars/category/ -> displays cars in the category
ex : .../cars/sedan -> displays cars in the sedan category
.../cars/category/id -> displays the details of the car from category which has id = 1
ex : .../cars/sedan/1 -> displays the details of the sedan car with id = 1
For routes 1 and 2 it's ok but I don't know how to do the last one. Can you help me please ?
data.js
export const cars = [
{
id: 1,
name: 'sedan',
models: [
{
id: 1,
name: 'model1',
image: '/sedan1.jpg',
},
{
id: 2,
name: 'model2',
image: '/sedan2.jpg',
},
{
id: 3,
name: 'model3',
image: '/sedan3.jpg',
},
],
},
{
id: 2,
name: 'suv',
models: [
{
id: 1,
name: 'model1',
image: '/suv1.jpg',
},
{
id: 2,
name: 'model2',
image: '/suv2.jpg',
},
{
id: 3,
name: 'model3',
image: '/suv3.jpg',
},
],
},
{
id: 3,
name: '4x4',
models: [
{
id: 1,
name: 'model1',
image: '/4x4_1.jpg',
},
{
id: 2,
name: 'model2',
image: '/4x4_2.jpg',
},
{
id: 3,
name: 'model3',
image: '/4x4_3.jpg',
},
],
},
];
/cars/index.js
import { cars } from '../../data';
import Link from 'next/link';
export default function Categories({ car }) {
return (
{car.map((c) => (
<Link key={c.id} href={`/cars/${c.name}`} passHref>
<div>{c.name}</div>
</Link>
))}
);
}
export const getStaticProps = async () => {
return {
props: {
car: cars,
},
};
};
/cars/[name].js
import React from 'react';
import { cars } from '../../data';
export default function CategoriesCars({ cars }) {
return (
<div>
{cars.models.map((m) => (
<p key={m.id}>{m.name}</p>
))}
</div>
);
}
export const getStaticPaths = async () => {
const paths = await cars.map((c) => ({
params: {
name: c.name,
},
}));
return { paths, fallback: false };
};
export const getStaticProps = async (context) => {
const { params } = context;
const response = await cars.filter((c) => c.name === params.name);
return {
props: {
cars: response[0],
},
};
};
The page folder must be:
pages/
cars/
[category]/
[id]/
index.jsx
index.jsx
then go /cars/sedan/2 you can access to category and id variables like this:
cars/[category]/[id]/index.jsx
import React from 'react';
import { useRouter } from 'next/router';
export default function Index() {
const router = useRouter();
// router.query.category -> sedan
// router.query.id -> 2
return <div>{JSON.stringify(router.query)}</div>;
}
// or
export const getServerSideProps = async (context) => {
const { params } = context;
console.log(params); // { category: 'sedan', id: '2' }
return {
props: {
cars: {},
},
};
};
// or if you wish use getStaticProps for SSG (with getStaticPaths)
export const getStaticPaths = async (context) => {
const paths = cars
.map((car) =>
car.models.map((model) => ({
params: {
id: model.id.toString(),
category: car.name,
},
}))
)
.flat(); // this is important
return { paths, fallback: false };
};
export const getStaticProps = async (context) => {
const { params } = context;
console.log(params);
return {
props: {
cars: {},
},
};
};
Example: StackBlitz

Why am I getting undefined after loading the page? But after refreshing the current page, I get normal data. How can I fix it? [duplicate]

This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 2 years ago.
I'm gettin undefined in hubConnection, and my program doesn't work, but after refreshing everything works correctly. I've tried to make hubConnection as simple property, but it didn't help me. One more thing that I've already tried is to create useRef hook and check if hubConnection if not undefined, if it not, then block the useEffect, but my messages after this action has stopped work.
Code of the program:
import React, { useCallback, useState, useEffect, useContext } from "react";
import { View, StyleSheet } from "react-native";
import { routes } from "../../../../Environment";
import { Icon } from 'react-native-elements'
import Font from "../../../data/fonts/Font";
import { GiftedChat, Bubble, Send, InputToolbar } from 'react-native-gifted-chat'
import { container } from 'tsyringe';
import ChatService from "../../../../api-service/chat-service/ChatService";
import { AuthContext } from "../../auth/AuthProvider";
import { HubConnection, HubConnectionBuilder } from "#microsoft/signalr";
const Chat = (props: any) => {
const chatService = container.resolve(ChatService);
const [messages, setMessages] = useState([]);
const [message, setMessage] = useState("");
const [hubConnection, setHubConnection] = useState<HubConnection>();
const { user } = useContext(AuthContext);
const getRandomInt = (max: number) => {
return Math.floor(Math.random() * Math.floor(max));
}
useEffect(() => {
setMessages([
{
_id: 1,
text: 'Hello dude',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
{
_id: 2,
text: 'Hello Tom',
createdAt: new Date(),
user: {
_id: user?.id.toString()!,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
{
_id: 3,
text: 'How are you?',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
])
const hubConnectionFunc = new HubConnectionBuilder()
.withUrl(routes.chatUrl)
.build();
hubConnectionFunc?.start().then(() => "Connection started!");
hubConnectionFunc.on("RecieveMessage", message => {
console.log(messages[0].text);
setMessages(previousMessages => GiftedChat.append(previousMessages, {
_id: getRandomInt(10000),
text: message,
createdAt: new Date(),
user: {
_id: user?.id.toString()!,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
}))
})
setHubConnection(hubConnectionFunc);
console.log(hubConnection);
}, [])
const onSend = useCallback((messages = []) => {
hubConnection?.invoke("SendMessage", messages[0].text)
.catch((err: any) => console.log(err));
setMessage("");
}, [])
const renderBubble = (props: any) => {
return (
<Bubble
{...props}
wrapperStyle={{
left: {
backgroundColor: "#F1F1F4",
},
right: {
backgroundColor: "#EB7A89"
}
}}
textStyle={{
left: {
color: "#000000"
},
right: {
color: "#FFFFFF"
}
}}
/>
);
}
const renderSend = (props: any) => {
return (
<Send {...props}>
<View style={styles.button}>
<Icon
name='paper-plane'
type='font-awesome'
color='white'
/>
</View>
</Send>
)
}
const renderInputToolbar = (props: any) => {
return (
<InputToolbar {...props} primaryStyle={{
borderWidth: 2,
justifyContent: "center",
alignItems: "center",
height: 44
}}
/>
)
}
return (
<View style={styles.chatWrapper}>
<GiftedChat
placeholder="Aa"
renderTime={() => <View></View>}
maxInputLength={500}
messages={messages}
onInputTextChanged={setMessage}
text={message}
onSend={onSend}
scrollToBottom
alwaysShowSend
user={{
_id: user?.id.toString()!,
name: user?.name!,
}}
renderBubble={renderBubble}
renderSend={renderSend}
renderInputToolbar={renderInputToolbar}
/>
</View >
)
}
NodeJS console after first loading
NodeJS console after refreshing the page
Some of your data not Loading 1st time but when you refresh your screen again it loads your data to fix this issue you can use async-await or && logic

React.js error: The service worker navigation preload request was cancelled before 'preloadResponse' settled

I have an issue with my React application (with Redux Saga), I'm getting the console error:
The service worker navigation preload request was cancelled before 'preloadResponse' settled. If you intend to use 'preloadResponse', use waitUntil() or respondWith() to wait for the promise to settle.
I see this error on the console only on Chrome, not in Firefox or Edge.
This error does not affect my application.
The following steps reproduce the error:
1. Main page upload.
2. Go to movie details page.
3. Go back to main page.
Main.jsx
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { mainActions } from '../../store/actions/actions';
import './Main.scss';
import { MoviesList, SearchPanel } from '../../components';
const propTypes = {};
const defaultProps = {};
class Main extends Component {
constructor(props) {
super(props);
this.handleSearchTextChange = this.handleSearchTextChange.bind(this);
this.handleLoadMoreButtonClick = this.handleLoadMoreButtonClick.bind(this);
this.handleMovieClick = this.handleMovieClick.bind(this);
this.handleFavoriteMovieClick = this.handleFavoriteMovieClick.bind(this);
}
componentDidMount() {
this.handleComponentDidMount();
}
handleComponentDidMount() {
const { moviesList } = this.props;
if (!moviesList || moviesList.length <= 0) {
this.getMovies(null, false);
}
}
handleLoadMoreButtonClick() {
this.getMovies(null, false);
}
handleMovieClick(e) {
if (e.target.className === 'movie') {
this.props.history.push(`/details/${e.currentTarget.dataset.id}`);
}
}
handleSearchTextChange(e) {
const { pageNumber, favoriteMoviesList } = this.props;
this.props.onSearchTextChange({
searchText: e.target.value,
pageNumber: pageNumber,
favoriteMoviesList: favoriteMoviesList
});
}
handleFavoriteMovieClick(e) {
const { id, name, posterId } = e.currentTarget.dataset;
const { moviesList, favoriteMoviesList } = this.props;
this.props.onUpdateFavoriteMovies({
updatedMovie: { id: id, name: name, posterId: posterId },
favoriteMoviesList: favoriteMoviesList,
moviesList: moviesList
});
}
getMovies(updatedSearchText, isSearchChange) {
const { searchText, pageNumber, favoriteMoviesList } = this.props;
this.props.onLoadMovies({
pageNumber: pageNumber,
favoriteMoviesList: favoriteMoviesList,
updatedSearchText: isSearchChange ? updatedSearchText : searchText,
isSearchChange: isSearchChange
});
}
render() {
const { searchText, isLoadingMoreMovies, isPager, moviesList } = this.props;
return (
<div className="main-area">
<SearchPanel
searchText={searchText}
onSearchTextChange={this.handleSearchTextChange}
/>
<MoviesList
pageName='movies'
moviesList={moviesList}
isLoadingMoreMovies={isLoadingMoreMovies}
isPager={isPager}
onLoadMoreClick={this.handleLoadMoreButtonClick}
onMovieClick={this.handleMovieClick}
onFavoriteMovieClick={this.handleFavoriteMovieClick}
/>
</div>
);
}
}
Main.propTypes = propTypes;
Main.defaultProps = defaultProps;
const mapStateToProps = (state) => {
return {
searchText: state.main.searchText,
pageNumber: state.main.pageNumber,
isLoadingMoreMovies: state.main.isLoadingMoreMovies,
isPager: state.main.isPager,
moviesList: state.main.moviesList,
favoriteMoviesList: state.main.favoriteMoviesList
};
};
const mapDispatchToProps = (dispatch) => {
return {
onLoadMovies: (request) => dispatch(mainActions.loadMovies(request)),
onSearchTextChange: (request) => dispatch(mainActions.searchTextChange(request)),
onUpdateFavoriteMovies: (request) => dispatch(mainActions.updateFavoriteMovies(request))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Main);
Details.jsx
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { detailsActions, mainActions } from '../../store/actions/actions';
import './Details.scss';
import { ActorsList, ButtonClick, CrewsList, FeaturesList, PageTitle, ProductionsList, Rating, Trailer } from '../../components';
import movieUtils from '../../utils/movie.utils';
const propTypes = {};
const defaultProps = {};
class Details extends Component {
constructor(props) {
super(props);
this.handleBackClick = this.handleBackClick.bind(this);
this.handleFavoriteMovieClick = this.handleFavoriteMovieClick.bind(this);
this.isFavorite = false;
}
componentDidMount() {
this.handleComponentDidMount();
}
handleComponentDidMount() {
if (this.props.moviesList.length <= 0) {
this.handleBackClick();
return;
}
const movieId = this.props.match.params.id;
if (!movieId) {
this.handleBackClick();
return;
}
this.props.onLoadMovieDetails(movieId);
this.updateIsFavorite(movieId);
}
numberWithCommas(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
updateIsFavorite(movieId) {
this.isFavorite = this.props.favoriteMoviesList.findIndex(movie => parseInt(movie.id) === parseInt(movieId)) > -1;
}
handleBackClick() {
this.props.history.push(`/`);
}
handleFavoriteMovieClick() {
const { movie, moviesList, favoriteMoviesList } = this.props;
this.props.onUpdateFavoriteMovies({
updatedMovie: { id: movie.id, name: movie.title, posterId: movie.poster_path },
favoriteMoviesList: favoriteMoviesList,
moviesList: moviesList
});
this.updateIsFavorite(movie.id);
}
render() {
const { movie, youtubeKey, credits } = this.props;
if (!movie) {
return null;
}
const { adult, poster_path, budget, genres, homepage, imdb_id, original_language, original_title,
overview, popularity, production_companies, production_countries, release_date, revenue, runtime, spoken_languages,
status, tagline, title, video, vote_average, vote_count } = movie;
const genresText = genres.map(genre => genre.name).join(', ');
const countriesText = production_countries.map(country => country.name).join(', ');
const languagesText = spoken_languages.map(language => language.name).join(', ');
const featuresList = [
{ item: 'Release Date', value: release_date },
{ item: 'Budget', value: `$${this.numberWithCommas(budget)}` },
{ item: 'Revenue', value: `$${this.numberWithCommas(revenue)}` },
{ item: 'Length', value: `${runtime} minutes` },
{ item: 'Popularity', value: popularity },
{ item: 'Original Title', value: original_title },
{ item: 'For Adults', value: adult ? 'Yes' : 'No' },
{ item: 'Original Language', value: original_language },
{ item: 'Spoken Languages', value: languagesText },
{ item: 'Countries', value: countriesText },
{ item: 'Status', value: status },
{ item: 'Is Video', value: video ? 'Yes' : 'No' }
];
const linksList = [];
if (homepage) {
linksList.push({ id: 1, name: 'Homepage', url: homepage });
}
if (imdb_id) {
linksList.push({ id: 2, name: 'IMDB', url: `https://www.imdb.com/title/${imdb_id}` });
}
const actorsList = movieUtils.removeDuplicates(credits ? credits.cast ? credits.cast : null : null, 'name');
const crewsList = movieUtils.removeDuplicates(credits ? credits.crew ? credits.crew : null : null, 'name');
return (
<div>
<section className="details-area">
<PageTitle
pageName='details'
pageTitle='Details'
/>
<ul className="details-content">
<li className="details-left" style={{ backgroundImage: `url('https://image.tmdb.org/t/p/original${poster_path}')` }}></li>
<li className="details-right">
<h2>{title} ({release_date.substr(0, 4)})</h2>
<p className="genres">{genresText}</p>
<p className="description short">{tagline}</p>
<Rating
rating={vote_average}
votesCount={this.numberWithCommas(vote_count)}
/>
<p className="description full">{overview}</p>
<div className="extra">
<FeaturesList
featuresList={featuresList.slice(0, 5)}
linksList={null}
isFavorite={this.isFavorite}
onFavoriteMovieClick={this.handleFavoriteMovieClick}
/>
{youtubeKey && <Trailer
youtubeKey={youtubeKey}
/>}
</div>
</li>
<div className="extra-features">
<FeaturesList
featuresList={featuresList.slice(5, featuresList.length)}
linksList={linksList}
isFavorite={null}
onFavoriteMovieClick={null}
/>
<ProductionsList
productionsList={production_companies}
/>
</div>
</ul>
</section>
<section className="actors-area">
<PageTitle
pageName='actors'
pageTitle='Cast'
/>
<ActorsList
actorsList={actorsList}
/>
</section>
<section className="crew-area">
<PageTitle
pageName='crew'
pageTitle='Crew'
/>
<CrewsList
crewsList={crewsList}
/>
</section>
<ButtonClick
buttonText={'Back'}
buttonTitle={'Back'}
isLoading={false}
onClick={this.handleBackClick}
/>
</div>
);
}
}
Details.propTypes = propTypes;
Details.defaultProps = defaultProps;
const mapStateToProps = (state) => {
return {
movie: state.details.movie,
youtubeKey: state.details.youtubeKey,
credits: state.details.credits,
moviesList: state.main.moviesList,
favoriteMoviesList: state.main.favoriteMoviesList
};
};
const mapDispatchToProps = (dispatch) => {
return {
onLoadMovieDetails: (movieId) => dispatch(detailsActions.loadDetails(movieId)),
onUpdateFavoriteMovies: (request) => dispatch(mainActions.updateFavoriteMovies(request))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Details);
What I already looked in:
Getting The service worker navigation preload request was cancelled before 'preloadResponse' settled
https://learn.microsoft.com/en-us/answers/questions/108004/getting-the-service-worker-navigation-preload-requ.html
https://support.google.com/mail/thread/4055804?hl=en
https://love2dev.com/pwa/service-worker-preload/
I tried to put this on Details.jsx page, but it didn't work:
self.addEventListener('fetch', event => {
event.respondWith(async function () {
// Respond from the cache if we can
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse; // Else, use the preloaded response, if it's there
const response = await event.preloadResponse;
if (response) return response; // Else try the network.
return fetch(event.request);
}());
});
self.addEventListener('activate', event => {
event.waitUntil(async function () {
// Feature-detect
if (self.registration.navigationPreload) { // Enable navigation preloads!
console.log('Enable navigation preloads!');
await self.registration.navigationPreload.enable();
} return;
})();
});
How can I solve this issue? Thanks.
Had same error, even my iframe wasn't loading..whatever video you are using from youtube use nocookie/embed in url. It's working for me.
Try changing https://www.youtube.com/watch?v=i8eBBG46H8A to
https://www.youtube-nocookie.com/embed/i8eBBG46H8A
Hope nocookie & embed helps..!!

Resources