Can't load mock data while mounting component - reactjs

I have a component that should render a list of mock items. The initial value is an empty array, and I want to load mock data during component render. But it doesn't work correctly - list in component is empty when I try to check it out by printing in console, but Redux Devtools shows that it is not. What am I doing wrong?
Component
import React, { Component } from 'react';
import TagsBlock from './TagsBlock';
import ActionButton from './ActionButton';
import { connect } from 'react-redux';
import { actionLoadCoctails, actionToggleDetail } from '../actions/actionCreators';
class ResultsCoctails extends Component {
componentDidMount() {
this.props.actionLoadCoctails();
}
list = this.props.loadCoctails.map(({ img, name, tags}, key) => {
const showDetail = (e) => {
e.preventDefault();
this.props.actionToggleDetail();
}
return (
<div
className="item"
key={`coctail-${key}`}
>
<a
href="#"
onClick={(e) => showDetail(e)}
>
<div className="img">
<img src={img} alt="error" />
</div>
<div className="desc">
<div className="name">{name}</div>
<TagsBlock tags={tags}></TagsBlock>
</div>
</a>
</div>
)
});
render() {
return (
<div className="result-coctails">
<div className="block">
{this.list}
</div>
<ActionButton txt="morŠµ"></ActionButton>
</div>
)
}
}
export default connect(state => ({
loadCoctails: state.loadCoctails
}), { actionLoadCoctails, actionToggleDetail })(ResultsCoctails);
Reducer
import { LOAD_COCTAILS } from '../constants';
const INIT_COCTAILS = [
{
img: 'some url',
name: 'Cocktail Mary',
tags: ['one', 'two', 'three'],
},
{
img: 'some url',
name: 'White Russian',
tags: ['one', 'two', 'three'],
},
{
img: 'some url',
name: 'Cocktail Mary',
tags: ['one', 'two', 'three'],
},
{
img: 'some url',
name: 'White Russian',
tags: ['one', 'two', 'three'],
},
{
img: 'some url',
name: 'Cocktail Mary',
tags: ['one', 'two', 'three'],
}
];
export const loadCoctails = (state = [], { type }) => {
switch(type) {
case LOAD_COCTAILS:
return {
...state, ...INIT_COCTAILS
}
default:
return state;
}
}
ActionCreator
import {
LOAD_COCTAILS,
TOGGLE_DETAIL,
LOAD_DETAIL
} from '../constants';
export const actionLoadCoctails = () => {
return {
type: LOAD_COCTAILS
}
}
export const actionToggleDetail = () => {
return {
type: TOGGLE_DETAIL
}
};
export const actionLoadDetail = (img, name, tags, deg, txt) => {
return {
type: LOAD_DETAIL,
img,
name,
tags,
deg,
txt
}
};

The problem is that the map() function can't work with objects - so, we should make an array and do map() with it:
const listArray = Object.values(this.props.loadCoctails);
const list = listArray.map(({ img, name, tags}, key) => {
.....

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;
}
}

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

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..!!

Cannot Find what is causing this : Warning: setState(...): Can only update a mounted or mounting component

So after looking over many different questions asking the about this warning, I have found that there is not one single reason why this would be occurring making it difficult to infer a solution on my own code.
So here is my code incase anyone has another pair of eyes they can put on it and spot maybe why i would be getting this error.
This error occurs when not on first arrival of the component but after leaving and returning to it again.
I have a smart container and a dumb component set up so here is the container:
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { listOrders, listUseCases } from '../../actions/order';
import { storeWithExpiration } from '../../utils/common.js';
import OrdersIndex from './OrdersIndex';
export class OrdersIndexContainer extends React.Component {
static propTypes = {
account: PropTypes.object.isRequired,
orders: PropTypes.object.isRequired,
platformMap: PropTypes.object.isRequired,
progress: PropTypes.number,
listOrdersAction: PropTypes.func.isRequired,
listUseCasesAction: PropTypes.func.isRequired,
};
render() {
const { orders, platformMap, progress } = this.props;
return (
<div>
<OrdersIndex
orders={ orders }
platformMap={ platformMap }
progress={ progress }
/>
</div>
);
}
renderOrderIndex = () => {
}
componentWillMount = () => {
const { account, listOrdersAction, listUseCasesAction } = this.props;
const token = storeWithExpiration.get('token');
listOrdersAction(token);
listUseCasesAction(account.id, token);
}
}
function mapStateToProps(state) {
const { account, orderList, progress } = state;
const orders = orderList.get('orders');
const platformMap = orderList.get('platformMap');
return { account, platformMap, orders, progress };
}
export default connect(mapStateToProps, {
listOrdersAction: listOrders,
listUseCasesAction: listUseCases,
})(OrdersIndexContainer);
And here is the dumb component:
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ReactDataGrid from 'react-data-grid';
import { Toolbar } from 'react-data-grid/addons';
import { Data } from 'react-data-grid/addons';
import moment from 'moment';
import { SIMPLE_DATE_FORMAT } from '../../config/app_config';
// import OrderWrapFormatter from './OrderWrapFormatter';
const TABLE_COLUMNS = [
{ key: 'cNumber', name: 'Customer #', width: 125 },
{ key: 'name', name: 'Name', width: 150 },
{ key: 'orderNumber', name: 'Order #', width: 90 },
{ key: 'platform', name: 'Platform' },
{ key: 'useCase', name: 'Use Case'/* , formatter: OrderWrapFormatter */ },
{ key: 'list', name: 'List' },
{ key: 'sku', name: 'SKU' },
{ key: 'startDate', name: 'Start Date' },
{ key: 'endDate', name: 'End Date' },
];
export default class OrdersIndex extends React.Component {
static propTypes = {
orders: PropTypes.object.isRequired,
platformMap: PropTypes.object.isRequired,
progress: PropTypes.number,
};
state = {
rows: [],
originalRows: [],
columns: TABLE_COLUMNS,
sortColumn: null,
sortDirection: null,
filters: {},
}
renderRows = (orders) => {
const _rows = [];
orders.map((o) => {
_rows.push({
key: o.order.id,
id: o.order.id,
cNumber: o.order.providerCustomerNumber,
name: o.order.company.name,
orderNumber: o.order.providerOrderNumber,
platform: o.platformUseCases[0].platform.description,
useCase: this.renderMulti(o.platformUseCases, 'useCase', 'description'),
list: this.renderMulti(o.listSKUs, 'dataSet', 'name'),
sku: this.renderMulti(o.listSKUs, 'fieldSet', 'name'),
startDate: moment(o.order.startDate).format(SIMPLE_DATE_FORMAT),
endDate: moment(o.order.endDate).format(SIMPLE_DATE_FORMAT),
});
return _rows;
});
return this.setState({
rows: _rows,
originalRows: _rows.slice(),
});
}
getRows = () => {
return Data.Selectors.getRows(this.state);
}
rowGetter = (rowIdx) => {
const rows = this.getRows();
return rows[rowIdx];
}
getSize = () => {
return this.getRows().length;
}
renderMulti = (multi, itemName, subItemName) => {
const objectArray = multi.map((object) => {
return object[itemName][subItemName];
});
return objectArray.join('\n');
}
handleGridSort = (sortColumn, sortDirection) => {
const { originalRows, rows } = this.state;
const comparer = (a, b) => {
if (sortDirection === 'ASC') {
return (a[sortColumn] > b[sortColumn]) ? 1 : -1;
}
else if (sortDirection === 'DESC') {
return (a[sortColumn] < b[sortColumn]) ? 1 : -1;
}
};
const newRows = sortDirection === 'NONE' ? originalRows.slice() : rows.sort(comparer);
this.setState({
rows: newRows,
});
}
handleRowUpdated = (e) => {
// merge updated row with current row and rerender by setting state
const { rows } = this.state;
Object.assign(rows[e.rowIdx], e.updated);
this.setState({
...rows,
});
}
handleFilterChange = (filter) => {
const { filters } = this.state;
const newFilters = Object.assign({}, filters);
if (filter.filterTerm) {
newFilters[filter.column.key] = filter;
}
else {
delete newFilters[filter.column.key];
}
this.setState({
filters: newFilters,
});
}
onClearFilters = () => {
// all filters removed
this.setState({
filters: {},
});
}
// Creates appropriate warnings to prevent entering
// the order form if the account is missing information
renderNotice = (message, buttonMessage, route) => {
return (
<div className="alert alert-warning">
<strong>Notice:</strong>
<p>{ message }</p>
<p>
<Link
to={ route }
className="btn btn-warning"
>
<i className='fa fa-plus'></i>
{ buttonMessage }
</Link>
</p>
</div>
);
}
render() {
const { platformMap, progress } = this.props;
const platformMessage = 'Your account is not associated with any platform use cases.' +
'You must select at least one use case before creating new orders.';
const platformButton = 'Add Use Cases';
const platformRoute = '/products';
return (
<div className="container">
<div className="row">
<div className="col-sm-12 col-md-8">
<h1>Orders</h1>
</div>
<div className="col-sm-12 col-md-4">
<span className="pull-right">
<Link
to="/orders/create/1"
className="btn btn-primary"
disabled
>
<i className='fa fa-plus'></i>Create New Order
</Link>
</span>
</div>
</div>
{ platformMap.size === 0 && progress === 0 ?
this.renderNotice(platformMessage, platformButton, platformRoute) : null }
<div className="row">
{ progress === 0 ?
<div className="col-md-12">
{ this.renderTable() }
</div> : null }
</div>
</div>
);
}
renderTable = () => {
const { orders } = this.props;
const { columns } = this.state;
return (
<div>
{ orders.size === 0 || orders === undefined ?
<p>Your account has no orders</p> :
<ReactDataGrid
onGridSort={ this.handleGridSort }
rowKey="key"
id="key"
columns={ columns }
rowGetter={ this.rowGetter }
rowsCount={ this.getSize() }
onRowUpdated={ this.handleRowUpdated }
toolbar={ <Toolbar enableFilter /> }
onAddFilter={ this.handleFilterChange }
onClearFilters={ this.onClearFilters }
minHeight={ 500 }
filterRowsButtonText="Search By Field"
/>
}
</div>
);
}
componentWillMount = () => {
const { orders } = this.props;
const columnArray =
TABLE_COLUMNS.map((c) => {
const copy = Object.assign({}, c);
copy.filterable = true;
copy.locked = true;
if (copy.key !== 'useCase') {
copy.sortable = true;
}
return copy;
});
this.setState({
columns: columnArray,
});
this.renderRows(orders);
}
componentWillReceiveProps = (nextProps) => {
const { orders } = nextProps;
if (orders.size > 0) {
this.renderRows(orders);
}
}
}
I understand this might be a lot but I cannot for the life of me determine what could be the cause. Thanks to anyone who takes a look.

React Material UI makeSelectable List Not Compatible With Nested ListItem Component

I have a problem that my makeSelectable code is not working when I used the ListItem from child component instead of using ListItem directly. Here is my example code (the workingLinkItems can be selected normally but the notWorkingLinkItems is not selectable).
import React, { Component, PropTypes } from 'react'
import { List, makeSelectable, ListItem } from 'material-ui/List'
import { wrapState } from 'helpers/utils'
const { func, shape, string, number } = PropTypes
class TryListItem extends Component {
static propTypes = {
onOpenLink: func.isRequired,
linkItem: shape({
key: number.isRequired,
link: string.isRequired,
text: string.isRequired,
}).isRequired,
}
handleOpenLink = () => {
this.props.onOpenLink(this.props.linkItem.link)
}
render () {
const { key, link, text } = this.props.linkItem
return <ListItem
value={key}
primaryText={text}
onTouchTap={this.handleOpenLink} />
}
}
let SelectableList = makeSelectable(List)
SelectableList = wrapState(SelectableList)
class TrySelectableList extends Component {
handleOpenLink = (location) => {
console.log('The page will be redirected to: ', location)
}
render () {
const links = [
{
key: 1,
link: '/home',
text: 'Home',
},
{
key: 2,
link: '/about',
text: 'About Us',
},
{
key: 3,
link: '/contact',
text: 'Contact Us',
},
]
const notWorkingLinkItems = links.map((link) => (
<TryListItem
onOpenLink={this.handleOpenLink}
linkItem={link} />
))
const workingLinkItems = links.map((link) => (
<ListItem
value={link.key + 3}
primaryText={link.text}
onTouchTap={this.handleOpenLink} />
))
return (
<div>
<SelectableList defaultValue={1}>
{notWorkingLinkItems}
{workingLinkItems}
</SelectableList>
</div>
)
}
}
export default TrySelectableList
Any idea what's wrong with my code?
Finally after a lot of trial tinkering with material-ui makeSelectable function. I ended up creating my own selectable style.
Here is my code solution for my problem:
import React, { Component, PropTypes } from 'react'
import { List, ListItem } from 'material-ui/List'
const { bool, func, shape, string, number } = PropTypes
class TryListItem extends Component {
static propTypes = {
selected: bool.isRequired,
onOpenLink: func.isRequired,
linkItem: shape({
link: string.isRequired,
text: string.isRequired,
}).isRequired,
}
handleOpenLink = () => {
this.props.onOpenLink(this.props.linkItem.link, this.props.linkItem.key)
}
render () {
const { key, link, text } = this.props.linkItem
const styles = this.props.selected
? { backgroundColor: 'rgba(0, 0, 0, 0.2)', }
: {}
return <ListItem
primaryText={text}
onTouchTap={this.handleOpenLink}
style={styles} />
}
}
class TrySelectableList extends Component {
componentWillMount = () => {
this.buildLink()
}
buildLink = (selectedIndex = 0) => {
const initialLinks = [
{
key: 1,
link: '/home',
text: 'Home',
selected: false,
},
{
key: 2,
link: '/about',
text: 'About Us',
selected: false,
},
{
key: 3,
link: '/contact',
text: 'Contact Us',
selected: false,
},
]
const links = initialLinks.map((link) => {
if (link.key === selectedIndex) {
link.selected = true
}
return link
})
this.setState({
links: links
})
}
handleOpenLink = (location, index) => {
console.log('The page will be redirected to: ', location)
this.buildLink(index)
}
render () {
const workingLinkItems = this.state.links.map((link) => (
<TryListItem
key={link.key}
selected={link.selected}
onOpenLink={this.handleOpenLink}
linkItem={link} />
))
return (
<div>
<List>
{workingLinkItems}
</List>
</div>
)
}
}
export default TrySelectableList

Resources