Skip to content

Commit e384ab7

Browse files
refactor: use a custom hook to consume the global state (#15)
* refactor: use local state for Transform component * refactor: use a custom hook to consume global state
1 parent 3a9b0e6 commit e384ab7

32 files changed

+2654
-2987
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
11
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
33

4-
name: Node.js CI
4+
name: CI
55

66
on:
77
push:
8-
branches: [ master ]
8+
branches: [master]
99
pull_request:
10-
branches: [ master ]
10+
branches: [master]
1111

1212
jobs:
13-
build:
14-
13+
job:
1514
runs-on: ubuntu-latest
1615

1716
strategy:
1817
matrix:
1918
node-version: [10.x, 12.x]
2019

2120
steps:
22-
- uses: actions/checkout@v2
23-
- name: Use Node.js ${{ matrix.node-version }}
24-
uses: actions/setup-node@v1
25-
with:
26-
node-version: ${{ matrix.node-version }}
27-
- run: yarn
28-
- run: yarn run build
29-
- run: yarn test
30-
- run: yarn run format
31-
- run: yarn run test:e2e
21+
- uses: actions/checkout@v2
22+
- name: Use Node.js ${{ matrix.node-version }}
23+
uses: actions/setup-node@v1
24+
with:
25+
node-version: ${{ matrix.node-version }}
26+
- run: yarn
27+
- run: yarn format:check
28+
- run: yarn run test

cypress/fixtures/example.json

-5
This file was deleted.

cypress/integration/behavior.spec.js

-13
This file was deleted.

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"@testing-library/react": "^9.3.2",
88
"@testing-library/user-event": "^7.1.2",
99
"css-to-react-native": "^3.0.0",
10-
"node-sass": "^4.13.1",
10+
"node-sass": "4.14.1",
1111
"postcss": "^7.0.26",
1212
"postcss-js": "^2.0.3",
1313
"react": "^16.12.0",
@@ -27,13 +27,13 @@
2727
"scripts": {
2828
"start": "react-scripts start",
2929
"build": "react-scripts build",
30-
"test": "react-scripts test",
30+
"test": "yarn test:unit && yarn test:e2e",
3131
"cy:run": "cypress run",
32+
"test:unit": "react-scripts test",
3233
"test:e2e": "start-server-and-test :3000 cy:run",
3334
"eject": "react-scripts eject",
34-
"format": "prettier --write tests/**/*.js src/**/*.{js,css,scss} *.md",
35-
"predeploy": "npm run build",
36-
"deploy": "surge --project ./build --domain https://csstox.surge.sh"
35+
"format:check": "prettier --check tests/**/*.js src/**/*.{js,css,scss} *.md",
36+
"format": "prettier --write tests/**/*.js src/**/*.{js,css,scss} *.md"
3737
},
3838
"eslintConfig": {
3939
"extends": "react-app"

src/App.js

+5-38
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,21 @@
1-
import React, { useState, useEffect } from "react";
1+
import React from "react";
22

33
import "./assets/css/global.css";
44

5+
import AppContext from "./AppContext";
56
import Header from "./components/header/Header";
6-
import Transform from "./components/transform/Transform";
77
import Title from "./components/title/Title";
8-
import { toJSS, toRN } from "./helpers/transform";
9-
10-
const initialInputCss = `font-size: 18px;\nline-height: 24px;\ncolor: red;`;
11-
12-
export const Context = React.createContext(null);
8+
import Transform from "./components/transform/Transform";
139

1410
function App() {
15-
const [outputType, setOutputType] = useState("React Native");
16-
const [inputCss, setInputCss] = useState(initialInputCss);
17-
const [outputCss, setOutputCss] = useState("");
18-
19-
useEffect(() => {
20-
if (inputCss === "") {
21-
setInputCss(initialInputCss);
22-
}
23-
24-
switch (outputType) {
25-
case "JSS":
26-
setOutputCss(toJSS(inputCss));
27-
break;
28-
case "React Native":
29-
setOutputCss(toRN(inputCss));
30-
break;
31-
default:
32-
setOutputCss("Unknown output type");
33-
}
34-
}, [inputCss, outputType, setOutputCss]);
35-
3611
return (
37-
<Context.Provider
38-
value={{
39-
outputType,
40-
inputCss,
41-
outputCss,
42-
outputTypeChanged: setOutputType,
43-
inputCssChanged: setInputCss,
44-
}}
45-
>
12+
<AppContext>
4613
<div className="wrapper">
4714
<Header />
4815
<Title />
4916
<Transform />
5017
</div>
51-
</Context.Provider>
18+
</AppContext>
5219
);
5320
}
5421

src/AppContext.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React, { createContext, useContext, useState } from "react";
2+
3+
export const Context = createContext();
4+
5+
export const useOutputType = () => useContext(Context);
6+
7+
const AppContext = ({ children }) => {
8+
const [outputType, setOutputType] = useState("React Native");
9+
return (
10+
<Context.Provider value={{ outputType, setOutputType }}>
11+
{children}
12+
</Context.Provider>
13+
);
14+
};
15+
16+
export default AppContext;

src/components/code-editor/code-editor.scss src/assets/css/editor.scss

-8
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,3 @@
1717
overflow: scroll;
1818
tab-size: 4;
1919
}
20-
21-
.code--input {
22-
background: #ecf2f5;
23-
}
24-
25-
.code--output {
26-
background: #e0ebf5;
27-
}

src/components/code-editor/CodeEditor.js

-37
This file was deleted.

src/components/code-editor/code-editor.test.js

-75
This file was deleted.

src/components/header/Header.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import React, { useContext } from "react";
1+
import React from "react";
2+
3+
// Custom hook to consume the global state
4+
import { useOutputType } from "../../AppContext";
25

36
import "./header.scss";
4-
import SelectBox from "../select-box/SelectBox";
5-
import { Context } from "../../App";
7+
import Select from "./select/Select";
68

79
const Header = () => {
8-
const { outputType } = useContext(Context);
10+
const { outputType } = useOutputType();
911

1012
return (
1113
<header>
1214
<div className="header-wrapper">
1315
<div>
1416
<h1>
1517
CSS to &nbsp;
16-
<SelectBox />
18+
<Select />
1719
</h1>
1820
<br />
1921
</div>

src/components/header/header.test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React from "react";
22
import { render, screen } from "@testing-library/react";
33

4-
import { Context } from "../../App";
4+
import { Context } from "../../AppContext";
55
import Header from "./Header";
66

77
test("should show the message with proper output type", () => {
8-
const contextValue = { outputType: "JSS" };
8+
const value = { outputType: "JSS" };
99
render(
10-
<Context.Provider value={contextValue}>
10+
<Context.Provider value={value}>
1111
<Header />
1212
</Context.Provider>
1313
);
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from "react";
2+
3+
// Custom hook to consume the global state
4+
import { useOutputType } from "../../../AppContext";
5+
6+
import "./select.scss";
7+
8+
const SelectBox = () => {
9+
const { setOutputType } = useOutputType();
10+
11+
return (
12+
<select
13+
className="select"
14+
data-testid="select"
15+
onChange={({ target }) => setOutputType(target.value)}
16+
>
17+
<option value="React Native">React Native</option>
18+
<option value="JSS">JSS</option>
19+
</select>
20+
);
21+
};
22+
23+
export default SelectBox;
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import userEvent from "@testing-library/user-event";
4+
5+
import { Context } from "../../../AppContext";
6+
import Select from "./Select";
7+
8+
test("should invoke the callback when value changes", async () => {
9+
const setOutputType = jest.fn();
10+
const value = { setOutputType };
11+
12+
render(
13+
<Context.Provider value={value}>
14+
<Select />
15+
</Context.Provider>
16+
);
17+
18+
await userEvent.selectOptions(screen.getByTestId("select"), ["JSS"]);
19+
20+
expect(setOutputType).toHaveBeenLastCalledWith("JSS");
21+
});

0 commit comments

Comments
 (0)