From b406bea04593a0b6320e6807f57872eb0ded5fdf Mon Sep 17 00:00:00 2001 From: Matt Rakow Date: Mon, 10 Aug 2020 14:47:30 -0700 Subject: [PATCH 1/4] Replace React view with DOM-only --- .../external-views/src/app/app.ts | 16 +++----- .../src/app/views/PrettyDiceRollerView.tsx | 40 ------------------- .../external-views/src/app/views/index.ts | 2 +- .../src/app/views/renderDiceRoller.ts | 33 +++++++++++++++ 4 files changed, 40 insertions(+), 51 deletions(-) delete mode 100644 examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx create mode 100644 examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts diff --git a/examples/hosts/app-integration/external-views/src/app/app.ts b/examples/hosts/app-integration/external-views/src/app/app.ts index 59c4d8fddfe1..8034be701478 100644 --- a/examples/hosts/app-integration/external-views/src/app/app.ts +++ b/examples/hosts/app-integration/external-views/src/app/app.ts @@ -5,11 +5,9 @@ import { Container } from "@fluidframework/container-loader"; import { getTinyliciousContainer } from "@fluidframework/get-tinylicious-container"; -import * as React from "react"; -import * as ReactDOM from "react-dom"; import { IDiceRoller } from "../component"; import { DiceRollerContainerRuntimeFactory } from "../container"; -import { PrettyDiceRollerView } from "./views"; +import { renderDiceRoller } from "./views"; // I'm choosing to put the docId in the hash just for my own convenience, so the URL will end up looking something // like http://localhost:8080/#1596520748752. This is not crucial to the scenario -- there should be no requirements @@ -41,18 +39,16 @@ async function getDiceRollerFromContainer(container: Container): Promise { // Get the container to use. Associate the data with the provided documentId, and run the provided code within. const container = await getTinyliciousContainer(documentId, DiceRollerContainerRuntimeFactory, createNew); const diceRoller = await getDiceRollerFromContainer(container); - await renderPrettyDiceRoller(diceRoller); + + // Given an IDiceRoller, we can render its data using the view we've created in our app. + const div = document.getElementById("content") as HTMLDivElement; + renderDiceRoller(diceRoller, div); + // Setting "fluidStarted" is just for our test automation // eslint-disable-next-line dot-notation window["fluidStarted"] = true; diff --git a/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx b/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx deleted file mode 100644 index 75d49c664bc7..000000000000 --- a/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -import React from "react"; -import { IDiceRoller } from "../../component"; - -interface IPrettyDiceRollerViewProps { - model: IDiceRoller; -} - -export const PrettyDiceRollerView: React.FC = - (props: React.PropsWithChildren) => { - const [diceValue, setDiceValue] = React.useState(props.model.value); - - React.useEffect(() => { - // useEffect runs async after render, so it's possible for the dice value to update after render but - // before we get our event listener registered. We refresh our dice value in case that happened. - setDiceValue(props.model.value); - const onDiceRolled = () => { - setDiceValue(props.model.value); - }; - props.model.on("diceRolled", onDiceRolled); - return () => { - props.model.off("diceRolled", onDiceRolled); - }; - }, [props.model]); - - // Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅) - const diceChar = String.fromCodePoint(0x267F + diceValue); - const diceColor = `hsl(${diceValue * 60}, 70%, 50%)`; - - return ( -
-
{diceChar}
- -
- ); - }; diff --git a/examples/hosts/app-integration/external-views/src/app/views/index.ts b/examples/hosts/app-integration/external-views/src/app/views/index.ts index 43083af8836d..e6d52fc53a69 100644 --- a/examples/hosts/app-integration/external-views/src/app/views/index.ts +++ b/examples/hosts/app-integration/external-views/src/app/views/index.ts @@ -3,4 +3,4 @@ * Licensed under the MIT License. */ -export * from "./PrettyDiceRollerView"; +export * from "./renderDiceRoller"; diff --git a/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts new file mode 100644 index 000000000000..11e82f303105 --- /dev/null +++ b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts @@ -0,0 +1,33 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { IDiceRoller } from "../../component"; + +export function renderDiceRoller(diceRoller: IDiceRoller, div: HTMLDivElement) { + const wrapperDiv = document.createElement("div"); + wrapperDiv.style.textAlign = "center"; + div.append(wrapperDiv); + + const diceCharDiv = document.createElement("div"); + diceCharDiv.style.fontSize = "200px"; + + const rollButton = document.createElement("button"); + rollButton.style.fontSize = "50px"; + rollButton.textContent = "Roll"; + // Call the roll method to modify the shared data when the button is clicked + rollButton.addEventListener("click", diceRoller.roll); + + wrapperDiv.append(diceCharDiv, rollButton); + + // Get the current value of the shared data to update the view whenever it changes. + const rerender = () => { + diceCharDiv.textContent = String.fromCodePoint(0x267F + diceRoller.value); + diceCharDiv.style.color = `hsl(${diceRoller.value * 60}, 70%, 50%)`; + }; + rerender(); + + // Use the diceRolled event to trigger the rerender whenever the value changes. + diceRoller.on("diceRolled", rerender); +} From dfae1f9a341f08ca05d1a55445e99759c3b59e35 Mon Sep 17 00:00:00 2001 From: Matt Rakow Date: Mon, 10 Aug 2020 14:49:25 -0700 Subject: [PATCH 2/4] Remove react deps --- examples/hosts/app-integration/external-views/package.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/hosts/app-integration/external-views/package.json b/examples/hosts/app-integration/external-views/package.json index ff5269ed6bc0..1279ba4390c1 100644 --- a/examples/hosts/app-integration/external-views/package.json +++ b/examples/hosts/app-integration/external-views/package.json @@ -34,9 +34,7 @@ "@fluidframework/aqueduct": "^0.25.0", "@fluidframework/container-loader": "^0.25.0", "@fluidframework/get-tinylicious-container": "^0.25.0", - "@fluidframework/map": "^0.25.0", - "react": "^16.10.2", - "react-dom": "^16.10.2" + "@fluidframework/map": "^0.25.0" }, "devDependencies": { "@fluidframework/build-common": "^0.18.0", @@ -47,8 +45,6 @@ "@types/jest-environment-puppeteer": "2.2.0", "@types/node": "^10.17.24", "@types/puppeteer": "1.3.0", - "@types/react": "^16.9.15", - "@types/react-dom": "^16.9.4", "@typescript-eslint/eslint-plugin": "~2.17.0", "@typescript-eslint/parser": "~2.17.0", "clean-webpack-plugin": "^3.0.0", From 323b7d8306ad5e16b2b4c1b707619177c7fb31d4 Mon Sep 17 00:00:00 2001 From: Matt Rakow Date: Mon, 10 Aug 2020 14:53:48 -0700 Subject: [PATCH 3/4] Comments and naming --- .../external-views/src/app/views/renderDiceRoller.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts index 11e82f303105..fb3a4259e180 100644 --- a/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts +++ b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts @@ -5,6 +5,11 @@ import { IDiceRoller } from "../../component"; +/** + * Render an IDiceRoller into a given div as a text character, with a button to roll it. + * @param diceRoller - The Data Object to be rendered + * @param div - The div to render into + */ export function renderDiceRoller(diceRoller: IDiceRoller, div: HTMLDivElement) { const wrapperDiv = document.createElement("div"); wrapperDiv.style.textAlign = "center"; @@ -22,12 +27,13 @@ export function renderDiceRoller(diceRoller: IDiceRoller, div: HTMLDivElement) { wrapperDiv.append(diceCharDiv, rollButton); // Get the current value of the shared data to update the view whenever it changes. - const rerender = () => { + const updateDiceChar = () => { + // Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅) diceCharDiv.textContent = String.fromCodePoint(0x267F + diceRoller.value); diceCharDiv.style.color = `hsl(${diceRoller.value * 60}, 70%, 50%)`; }; - rerender(); + updateDiceChar(); // Use the diceRolled event to trigger the rerender whenever the value changes. - diceRoller.on("diceRolled", rerender); + diceRoller.on("diceRolled", updateDiceChar); } From ea7c9a0ee6c2bdada67f44ac25618fe06e7cc0a6 Mon Sep 17 00:00:00 2001 From: Matt Rakow Date: Tue, 11 Aug 2020 10:09:59 -0700 Subject: [PATCH 4/4] Fix merge --- .../src/app/views/PrettyDiceRollerView.tsx | 40 ------------------- .../src/app/views/renderDiceRoller.ts | 2 +- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx diff --git a/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx b/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx deleted file mode 100644 index 0be8cb71b9df..000000000000 --- a/examples/hosts/app-integration/external-views/src/app/views/PrettyDiceRollerView.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -import React from "react"; -import { IDiceRoller } from "../../dataObject"; - -interface IPrettyDiceRollerViewProps { - model: IDiceRoller; -} - -export const PrettyDiceRollerView: React.FC = - (props: React.PropsWithChildren) => { - const [diceValue, setDiceValue] = React.useState(props.model.value); - - React.useEffect(() => { - // useEffect runs async after render, so it's possible for the dice value to update after render but - // before we get our event listener registered. We refresh our dice value in case that happened. - setDiceValue(props.model.value); - const onDiceRolled = () => { - setDiceValue(props.model.value); - }; - props.model.on("diceRolled", onDiceRolled); - return () => { - props.model.off("diceRolled", onDiceRolled); - }; - }, [props.model]); - - // Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅) - const diceChar = String.fromCodePoint(0x267F + diceValue); - const diceColor = `hsl(${diceValue * 60}, 70%, 50%)`; - - return ( -
-
{diceChar}
- -
- ); - }; diff --git a/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts index fb3a4259e180..7fdf6e991111 100644 --- a/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts +++ b/examples/hosts/app-integration/external-views/src/app/views/renderDiceRoller.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. */ -import { IDiceRoller } from "../../component"; +import { IDiceRoller } from "../../dataObject"; /** * Render an IDiceRoller into a given div as a text character, with a button to roll it.