From 756af8507defc740500087272795715ea3e95c00 Mon Sep 17 00:00:00 2001 From: Paul Dias Date: Fri, 31 Jan 2020 11:38:14 -0500 Subject: [PATCH] feat: add support for manualReloadFromPropChanges prop (#67) --- README.md | 11 +++++++- src/index.js | 29 +++++++++++++++++++--- test/index.test.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9b930e6..7ba88d1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ This library has [the same support characteristics as the Brightcove Player Load - [Props](#props) - [`attrs`](#attrs) - [`baseUrl`](#baseurl) + - [`manualReloadFromPropChanges`](#manualreloadfrompropchanges) - [Other Props](#other-props) - [Effects of Prop Changes](#effects-of-prop-changes) - [View the Demo](#view-the-demo) @@ -96,6 +97,14 @@ Used to override the base URL for the Brightcove Player being embedded. Most users will never need this prop. By default, players are loaded from Brightcove's player CDN (`players.brightcove.net`). +### `manualReloadFromPropChanges` + +Type: `boolean` + +Used to specify if reloading the player after prop changes will be handled manually. This can be done by calling `refToReactPlayerLoader.loadPlayer()`. + +See [Effects of Prop Changes](#effects-of-prop-changes) below for the effects of prop changes. + ### Other Props All props not specified above are passed to the [Brightcove Player Loader](https://github.com/brightcove/player-loader#parameters) with a few differences: @@ -119,7 +128,7 @@ The following props will update the player's state _without_ a reload: - `playlistVideoId` - `videoId` -All other prop changes will cause a complete dispose/reload. +All other prop changes, excluding props that are `function`'s, will cause a complete dispose/reload. ## View the Demo diff --git a/src/index.js b/src/index.js index 5026ad8..2daf8b2 100644 --- a/src/index.js +++ b/src/index.js @@ -45,6 +45,10 @@ class ReactPlayerLoader extends React.Component { * @param {Object} [props.attrs] * Used to set attributes on the component element that contains the * embedded Brightcove Player. + * + * @param {boolean} [props.manualReloadFromPropChanges] + * Used to specify if reloading the player after prop changes will be handled manually. + * */ constructor(props) { super(props); @@ -52,6 +56,7 @@ class ReactPlayerLoader extends React.Component { this.setRefNode = ref => { this.refNode = ref; }; + this.loadPlayer = this.loadPlayer.bind(this); } /** @@ -123,6 +128,7 @@ class ReactPlayerLoader extends React.Component { // Delete props that are not meant to be passed to player-loader. delete options.attrs; delete options.baseUrl; + delete options.manualReloadFromPropChanges; // If a base URL is provided, it should only apply to this player load. // This means we need to back up the original base URL and restore it @@ -325,6 +331,19 @@ class ReactPlayerLoader extends React.Component { const previous = prevProps[key]; const current = this.props[key]; + // Do not compare functions + if (typeof current === 'function') { + return acc; + } + + if (typeof current === 'object' && current !== null) { + if (JSON.stringify(current) !== JSON.stringify(previous)) { + acc[key] = true; + } + + return acc; + } + if (current !== previous) { acc[key] = true; } @@ -332,10 +351,12 @@ class ReactPlayerLoader extends React.Component { return acc; }, {}); - // Dispose and recreate the player if any changed keys cannot be handled. - if (Object.keys(changes).some(k => UPDATEABLE_PROPS.indexOf(k) === -1)) { - this.loadPlayer(); - return; + if (!this.props.manualReloadFromPropChanges) { + // Dispose and recreate the player if any changed keys cannot be handled. + if (Object.keys(changes).some(k => UPDATEABLE_PROPS.indexOf(k) === -1)) { + this.loadPlayer(); + return; + } } this.updatePlayer(changes); diff --git a/test/index.test.js b/test/index.test.js index 5167c8c..0f6dab5 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -623,4 +623,66 @@ QUnit.module('ReactPlayerLoader', { rerender = render(React.createElement(ReactPlayerLoader, props)).rerender; }); + + QUnit.test('loadPlayer() method reloads player', function(assert) { + const done = assert.async(2); + + const props = { + accountId: '1', + applicationId: 'foo', + onSuccess: ({ref, type}) => { + assert.ok(true, 'the success callback was called'); + done(); + } + }; + + const reactPlayerLoader = ReactDOM.render( + React.createElement(ReactPlayerLoader, props), + this.fixture + ); + + reactPlayerLoader.loadPlayer(); + }); + + QUnit.test('set manualReloadFromPropChanges to true', function(assert) { + const done = assert.async(2); + let rerender; + const props = { + accountId: '1', + applicationId: 'foo', + manualReloadFromPropChanges: true, + onSuccess: ({ref, type}) => { + if (props.applicationId !== 'bar') { + props.applicationId = 'bar'; + done(); + } + rerender(React.createElement(ReactPlayerLoader, props)); + assert.ok(true, 'the success callback was called'); + done(); + } + }; + + rerender = render(React.createElement(ReactPlayerLoader, props)).rerender; + }); + + QUnit.test('set manualReloadFromPropChanges to false', function(assert) { + const done = assert.async(3); + let rerender; + const props = { + accountId: '1', + applicationId: 'foo', + manualReloadFromPropChanges: false, + onSuccess: ({ref, type}) => { + if (props.applicationId !== 'bar') { + props.applicationId = 'bar'; + done(); + } + rerender(React.createElement(ReactPlayerLoader, props)); + assert.ok(true, 'the success callback was called'); + done(); + } + }; + + rerender = render(React.createElement(ReactPlayerLoader, props)).rerender; + }); });