diff --git a/.prettierrc b/.prettierrc
index e69de29bb..cbc61f68e 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -0,0 +1 @@
+trailingComma: none
\ No newline at end of file
diff --git a/__tests__/regression/fix-2315.test.js b/__tests__/regression/fix-2315.test.js
new file mode 100644
index 000000000..193cf464f
--- /dev/null
+++ b/__tests__/regression/fix-2315.test.js
@@ -0,0 +1,35 @@
+// Test fix of #2315: Slider crashing after a state change in parent component
+import React from "react";
+import { render, fireEvent } from "@testing-library/react";
+
+import { getCurrentSlideContent, getSlidesCount } from "../../test-utils";
+import { GenericSliderComponent } from "../TestComponents";
+
+function TestSlider() {
+ const [count, setCount] = React.useState();
+
+ return (
+
+
+
+
+ );
+}
+
+describe("State change in parent component of slider", () => {
+ it("Slider shoud work afer clicking on Increment button", function() {
+ const { container } = render();
+ fireEvent(
+ container.getElementsByClassName("increment-button")[0],
+ new MouseEvent("click", {
+ bubbles: true,
+ cancelable: true
+ })
+ );
+ // Throws an error "Maximum update depth exceeded." if the bug exists
+ expect(getCurrentSlideContent(container)).toEqual("1");
+ expect(getSlidesCount(container)).toEqual(13);
+ });
+});
diff --git a/__tests__/utils/filterSettings.test.js b/__tests__/utils/filterSettings.test.js
new file mode 100644
index 000000000..fa431b195
--- /dev/null
+++ b/__tests__/utils/filterSettings.test.js
@@ -0,0 +1,18 @@
+import { filterSettings } from "../../src/utils/innerSliderUtils";
+
+describe("filterSettings", () => {
+ it("returns empty object if there are no valid settings", () => {
+ expect(filterSettings({})).toEqual({});
+ expect(filterSettings({ age: 10 })).toEqual({});
+ });
+ it("return an object with valid settings and omits extra properties", () => {
+ expect(filterSettings({ arrows: true, dots: true })).toEqual({
+ arrows: true,
+ dots: true
+ });
+ expect(filterSettings({ arrows: true, dots: true, age: 10 })).toEqual({
+ arrows: true,
+ dots: true
+ });
+ });
+});
diff --git a/package.json b/package.json
index c7537de36..1f8760f50 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,8 @@
"gen": "node examples/scripts/generateExampleConfigs.js && node examples/scripts/generateExamples.js && xdg-open docs/jquery.html",
"precommit": "lint-staged",
"test": "jest",
- "test-watch": "jest --watch"
+ "test-watch": "jest --watch",
+ "clear-jest": "jest --clearCache"
},
"author": "Kiran Abburi",
"license": "MIT",
diff --git a/src/inner-slider.js b/src/inner-slider.js
index aba39da9d..e6efb784b 100644
--- a/src/inner-slider.js
+++ b/src/inner-slider.js
@@ -134,7 +134,8 @@ export class InnerSlider extends React.Component {
}
if (
typeof prevProps[key] === "object" ||
- typeof prevProps[key] === "function"
+ typeof prevProps[key] === "function" ||
+ isNaN(prevProps[key])
) {
continue;
}
diff --git a/src/slider.js b/src/slider.js
index 82c91a912..36225013e 100644
--- a/src/slider.js
+++ b/src/slider.js
@@ -4,7 +4,7 @@ import React from "react";
import { InnerSlider } from "./inner-slider";
import json2mq from "json2mq";
import defaultProps from "./default-props";
-import { canUseDOM } from "./utils/innerSliderUtils";
+import { canUseDOM, filterSettings } from "./utils/innerSliderUtils";
const enquire = canUseDOM() && require("enquire.js");
export default class Slider extends React.Component {
@@ -198,14 +198,17 @@ export default class Slider extends React.Component {
if (settings === "unslick") {
const className = "regular slider " + (this.props.className || "");
return {children}
;
- } else if (newChildren.length <= settings.slidesToShow && !settings.infinite) {
+ } else if (
+ newChildren.length <= settings.slidesToShow &&
+ !settings.infinite
+ ) {
settings.unslick = true;
}
return (
{newChildren}
diff --git a/src/utils/innerSliderUtils.js b/src/utils/innerSliderUtils.js
index c06029d0a..98a37e917 100644
--- a/src/utils/innerSliderUtils.js
+++ b/src/utils/innerSliderUtils.js
@@ -1,4 +1,5 @@
import React from "react";
+import defaultProps from "../default-props";
export function clamp(number, lowerBound, upperBound) {
return Math.max(lowerBound, Math.min(number, upperBound));
@@ -6,10 +7,10 @@ export function clamp(number, lowerBound, upperBound) {
export const safePreventDefault = event => {
const passiveEvents = ["onTouchStart", "onTouchMove", "onWheel"];
- if(!passiveEvents.includes(event._reactName)) {
+ if (!passiveEvents.includes(event._reactName)) {
event.preventDefault();
}
-}
+};
export const getOnDemandLazySlides = spec => {
let onDemandSlides = [];
@@ -386,9 +387,12 @@ export const swipeMove = (e, spec) => {
let touchSwipeLength = touchObject.swipeLength;
if (!infinite) {
if (
- (currentSlide === 0 && (swipeDirection === "right" || swipeDirection === "down")) ||
- (currentSlide + 1 >= dotCount && (swipeDirection === "left" || swipeDirection === "up")) ||
- (!canGoNext(spec) && (swipeDirection === "left" || swipeDirection === "up"))
+ (currentSlide === 0 &&
+ (swipeDirection === "right" || swipeDirection === "down")) ||
+ (currentSlide + 1 >= dotCount &&
+ (swipeDirection === "left" || swipeDirection === "up")) ||
+ (!canGoNext(spec) &&
+ (swipeDirection === "left" || swipeDirection === "up"))
) {
touchSwipeLength = touchObject.swipeLength * edgeFriction;
if (edgeDragged === false && onEdge) {
@@ -849,3 +853,14 @@ export const canUseDOM = () =>
window.document &&
window.document.createElement
);
+
+export const validSettings = Object.keys(defaultProps);
+
+export function filterSettings(settings) {
+ return validSettings.reduce((acc, settingName) => {
+ if (settings.hasOwnProperty(settingName)) {
+ acc[settingName] = settings[settingName];
+ }
+ return acc;
+ }, {});
+}