Skip to content

Commit 32e3c7a

Browse files
R Naborsrickhanlonii
andauthored
Banner scheduling and snooze functionality (#3283)
Co-authored-by: Ricky <[email protected]>
1 parent 2e02d9c commit 32e3c7a

File tree

2 files changed

+46
-15
lines changed

2 files changed

+46
-15
lines changed

content/blog/2020-09-22-introducing-the-new-jsx-transform.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: [lunaruan]
55

66
Although React 17 [doesn't contain new features](/blog/2020/08/10/react-v17-rc.html), it will provide support for a new version of the JSX transform. In this post, we will describe what it is and how to try it.
77

8-
## What's a JSX Transform?
8+
## What's a JSX Transform? {#whats-a-jsx-transform}
99

1010
Browsers don't understand JSX out of the box, so most React users rely on a compiler like Babel or TypeScript to **transform JSX code into regular JavaScript**. Many preconfigured toolkits like Create React App or Next.js also include a JSX transform under the hood.
1111

@@ -24,7 +24,7 @@ Upgrading to the new transform is completely optional, but it has a few benefits
2424

2525
Now let's take a closer look at the differences between the old and the new transform.
2626

27-
## What’s Different in the New Transform?
27+
## What’s Different in the New Transform? {#whats-different-in-the-new-transform}
2828

2929
When you use JSX, the compiler transforms it into React function calls that the browser can understand. **The old JSX transform** turned JSX into `React.createElement(...)` calls.
3030

@@ -86,7 +86,7 @@ Note how our original code **did not need to import React** to use JSX anymore!
8686
>
8787
> The functions inside `react/jsx-runtime` and `react/jsx-dev-runtime` must only be used by the compiler transform. If you need to manually create elements in your code, you should keep using `React.createElement`. It will continue to work and is not going away.
8888
89-
## How to Upgrade to the New JSX Transform
89+
## How to Upgrade to the New JSX Transform {#how-to-upgrade-to-the-new-jsx-transform}
9090

9191
If you aren't ready to upgrade to the new JSX transform or if you are using JSX for another library, don't worry. The old transform will not be removed and will continue to be supported.
9292

@@ -97,23 +97,23 @@ If you want to upgrade, you will need two things:
9797

9898
Since the new JSX transform doesn't require React to be in scope, [we've also prepared an automated script](#removing-unused-react-imports) that will remove the unnecessary imports from your codebase.
9999

100-
### Create React App
100+
### Create React App {#create-react-app}
101101

102102
Create React App support [has been added](https://github.com/facebook/create-react-app/pull/9645) and will be available in the [upcoming v4.0 release](https://gist.github.com/iansu/4fab7a9bfa5fa6ebc87a908c62f5340b) which is currently in beta testing.
103103

104-
### Next.js
104+
### Next.js {#nextjs}
105105

106106
Next.js [v9.5.3](https://github.com/vercel/next.js/releases/tag/v9.5.3)+ uses the new transform for compatible React versions.
107107

108-
### Gatsby
108+
### Gatsby {#gatsby}
109109

110110
Gatsby [v2.24.5](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/CHANGELOG.md#22452-2020-08-28)+ uses the new transform for compatible React versions.
111111

112112
>Note
113113
>
114114
>If you get [this Gatsby error](https://github.com/gatsbyjs/gatsby/issues/26979) after upgrading to React `17.0.0-rc.2`, run `npm update` to fix it.
115115
116-
### Manual Babel Setup
116+
### Manual Babel Setup {#manual-babel-setup}
117117

118118
Support for the new JSX transform is available in Babel [v7.9.0](https://babeljs.io/blog/2020/03/16/7.9.0) and above.
119119

@@ -173,7 +173,7 @@ Starting from Babel 8, `"automatic"` will be the default runtime for both plugin
173173
>
174174
> If you use JSX with a library other than React, you can use [the `importSource` option](https://babeljs.io/docs/en/babel-preset-react#importsource) to import from that library instead -- as long as it provides the necessary entry points. Alternatively, you can keep using the classic transform which will continue to be supported.
175175
176-
### ESLint
176+
### ESLint {#eslint}
177177

178178
If you are using [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react), the `react/jsx-uses-react` and `react/react-in-jsx-scope` rules are no longer necessary and can be turned off or removed.
179179

@@ -188,15 +188,15 @@ If you are using [eslint-plugin-react](https://github.com/yannickcr/eslint-plugi
188188
}
189189
```
190190

191-
### TypeScript
191+
### TypeScript {#typescript}
192192

193193
TypeScript supports the JSX transform in [v4.1 beta](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#jsx-factories).
194194

195-
### Flow
195+
### Flow {#flow}
196196

197197
Flow supports the new JSX transform in [v0.126.0](https://github.com/facebook/flow/releases/tag/v0.126.0) and up.
198198

199-
## Removing Unused React Imports
199+
## Removing Unused React Imports {#removing-unused-react-imports}
200200

201201
Because the new JSX transform will automatically import the necessary `react/jsx-runtime` functions, React will no longer need to be in scope when you use JSX. This might lead to unused React imports in your code. It doesn't hurt to keep them, but if you'd like to remove them, we recommend running a [“codemod”](https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb) script to remove them automatically:
202202

@@ -261,6 +261,6 @@ function App() {
261261

262262
In addition to cleaning up unused imports, this will also help you prepare for a future major version of React (not React 17) which will support ES Modules and not have a default export.
263263

264-
## Thanks
264+
## Thanks {#thanks}
265265

266266
We'd like to thank Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, and Flow maintainers for their help implementing and integrating the new JSX transform. We also want to thank the React community for their feedback and discussion on the related [technical RFC](https://github.com/reactjs/rfcs/pull/107).

src/components/Banner/BannerContextManager.js

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@ import React, {useState, useLayoutEffect} from 'react';
1010
import BannerContext from './BannerContext';
1111

1212
let activeBanner = null;
13+
let snoozeStartDate = null;
14+
const today = new Date();
15+
16+
function addTimes(date, days) {
17+
const time = new Date(date);
18+
time.setDate(time.getDate() + days);
19+
return time;
20+
}
1321

1422
// Example usage:
1523
// activeBanner = {
16-
// storageId: 'dismiss_banner_blm',
24+
// storageId: 'react_banner_XX',
1725
// normalHeight: 60,
1826
// smallHeight: 80,
27+
// campaignStartDate: '2020-09-20Z', // the Z is for UTC
28+
// campaignEndDate: '2020-10-31Z', // the Z is for UTC
29+
// snoozeForDays: 7,
1930
// content: dismiss => (
2031
// <div>
2132
// <a href="test">Test</a> <button onClick={dismiss}>close</button>
@@ -25,7 +36,27 @@ let activeBanner = null;
2536

2637
if (activeBanner) {
2738
try {
28-
if (localStorage.getItem(activeBanner.storageId)) {
39+
if (localStorage[activeBanner.storageId]) {
40+
snoozeStartDate = new Date(
41+
parseInt(localStorage.getItem(activeBanner.storageId), 10),
42+
);
43+
}
44+
} catch (err) {
45+
// Ignore.
46+
}
47+
48+
try {
49+
// If it's too early or long past the campaign, don't show the banner:
50+
if (
51+
today < new Date(activeBanner.campaignStartDate) ||
52+
today > new Date(activeBanner.campaignEndDate)
53+
) {
54+
activeBanner = null;
55+
// If we're in the campaign window, but the snooze has been set and it hasn't expired:
56+
} else if (
57+
snoozeStartDate &&
58+
addTimes(snoozeStartDate, activeBanner.snoozeForDays) >= today
59+
) {
2960
activeBanner = null;
3061
}
3162
} catch (err) {
@@ -51,7 +82,7 @@ export default function BannerContextManager({children}: Props) {
5182
banner,
5283
dismiss: () => {
5384
try {
54-
localStorage.setItem(banner.storageId, 'true');
85+
localStorage.setItem(banner.storageId, Date.now().toString());
5586
} catch (err) {
5687
// Ignore.
5788
}

0 commit comments

Comments
 (0)