Skip to content

Commit

Permalink
split context in two
Browse files Browse the repository at this point in the history
  • Loading branch information
andrico1234 committed Jul 17, 2019
1 parent 46b7032 commit a471cd0
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 67 deletions.
4 changes: 2 additions & 2 deletions src/components/CalculateNodeCount.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useEffect } from 'react';
import { Skill } from 'models';
import SkillContext from '../context/SkillContext';
import SkillTreeContext from '../context/SkillTreeContext';

interface Props {
data: Skill[];
Expand All @@ -17,7 +17,7 @@ function calculateNodeCount(data: Skill[]): number {
}

function CalculateNodeCount({ data }: Props) {
const { addToSkillCount } = useContext(SkillContext);
const { addToSkillCount } = useContext(SkillTreeContext);

useEffect(() => {
const count = calculateNodeCount(data);
Expand Down
10 changes: 3 additions & 7 deletions src/components/SkillNode.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import classnames from 'classnames';
import { throttle, Cancelable, isEmpty } from 'lodash';
import { throttle, Cancelable } from 'lodash';
import Tippy from '@tippy.js/react';
import SkillContext from '../context/SkillContext';
import SkillTreeContext from '../context/SkillTreeContext';
import { LOCKED_STATE, UNLOCKED_STATE, SELECTED_STATE } from './constants';
import SkillTreeSegment from './SkillTreeSegment';
import TooltipContent from './ui/TooltipContent';
Expand All @@ -19,7 +19,7 @@ interface State {
}

class SkillNode extends React.Component<Props, State> {
static contextType = SkillContext;
static contextType = SkillTreeContext;
private skillNodeRef: React.RefObject<HTMLDivElement>;
private throttledResize: VoidFunction & Cancelable;
private childWidth: number = 0;
Expand Down Expand Up @@ -90,10 +90,6 @@ class SkillNode extends React.Component<Props, State> {
this.calculateOverlayWidth();

window.addEventListener('resize', this.throttledResize);

if (isEmpty(this.context.skills)) {
return this.updateState(UNLOCKED_STATE);
}
}

componentWillUnmount() {
Expand Down
5 changes: 3 additions & 2 deletions src/components/SkillTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Skill } from '../models';
import SkillTreeSegment from './SkillTreeSegment';
import HSeparator from './ui/HSeparator';
import CalculateTotalNodes from './CalculateNodeCount';
import { SkillTreeProvider } from '../context/SkillTreeContext';

interface Props {
data: Skill[];
Expand Down Expand Up @@ -31,7 +32,7 @@ function SkillTree({ data, title }: Props) {
}, []);

return (
<React.Fragment>
<SkillTreeProvider treeId={title}>
<CalculateTotalNodes data={data} />
<div className="SkillTree__container">
<h2 className="SkillTree__title">{title}</h2>
Expand All @@ -50,7 +51,7 @@ function SkillTree({ data, title }: Props) {
})}
</div>
</div>
</React.Fragment>
</SkillTreeProvider>
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/SkillTreeGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext } from 'react';
import SkillContext from '../context/SkillContext';
import SkillAppContext from '../context/SkillAppContext';

export interface TreeData {
skillCount: number;
Expand All @@ -13,7 +13,7 @@ interface Props {

function SkillTreeGroup(props: Props) {
const { skillCount, selectedSkillCount, resetSkills } = useContext(
SkillContext
SkillAppContext
);

const treeData = {
Expand Down
11 changes: 8 additions & 3 deletions src/components/SkillTreeSegment.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useRef, useEffect, useState, useContext } from 'react';
import { throttle } from 'lodash';
import { throttle, isEmpty } from 'lodash';
import SkillNode from './SkillNode';
import SkillEdge from './SkillEdge';
import { Skill, ParentPosition, ChildPosition, NodeState } from '../models';
import { Nullable } from '../models/utils';
import SkillContext from '../context/SkillContext';
import SkillTreeContext from '../context/SkillTreeContext';
import { SELECTED_STATE, LOCKED_STATE, UNLOCKED_STATE } from './constants';

interface Props {
Expand All @@ -27,8 +27,9 @@ const SkillTreeSegment = React.memo(function({
}: Props) {
const [childPosition, setChildPosition] = useState(defaultParentPosition);
const { skills, updateSkillState, decrementSelectedSkillCount } = useContext(
SkillContext
SkillTreeContext
);

const skillNodeRef: React.MutableRefObject<Nullable<HTMLDivElement>> = useRef(
null
);
Expand Down Expand Up @@ -75,6 +76,10 @@ const SkillTreeSegment = React.memo(function({
window.addEventListener('resize', throttle(calculatePosition, 250));
calculatePosition();

if (isEmpty(skills)) {
return updateSkillState(skill.id, UNLOCKED_STATE);
}

return function cleanup() {
window.removeEventListener('resize', throttle(calculatePosition));
};
Expand Down
15 changes: 10 additions & 5 deletions src/components/__tests__/CalculateNodeCount.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { useContext } from 'react';
import { render } from '@testing-library/react';
import CalculateSkillNodes from '../CalculateNodeCount';
import { Skill } from 'models';
import SkillContext from '../../context/SkillContext';
import SkillAppContext from '../../context/SkillAppContext';
import { SkillTreeProvider } from '../../context/SkillTreeContext';
import {
legsPullData,
legsPushData,
Expand All @@ -13,7 +14,7 @@ interface GetDummyCounterProps {
}

function GetDummyCounter({ children }: GetDummyCounterProps) {
const { skillCount } = useContext(SkillContext);
const { skillCount } = useContext(SkillAppContext);

return children(skillCount);
}
Expand All @@ -29,7 +30,11 @@ function renderComponent(data: Skill[]) {
<GetDummyCounter>
{skillCount => {
counter = skillCount;
return <CalculateSkillNodes data={data} />;
return (
<SkillTreeProvider treeId="hey">
<CalculateSkillNodes data={data} />>
</SkillTreeProvider>
);
}}
</GetDummyCounter>
);
Expand All @@ -47,14 +52,14 @@ describe('CalculateSkillNodes component', () => {
expect(getCounter).toBe(0);
});

xit('should correctly calculate a single branch tree', async () => {
it('should correctly calculate a single branch tree', async () => {
const { getCounter, debug } = renderComponent(legsPullData);
debug();

expect(getCounter).toBe(6);
});

xit('should correctly calculate a tree with multiples branches', () => {
it('should correctly calculate a tree with multiples branches', () => {
const { getCounter } = renderComponent(legsPushData);

expect(getCounter).toBe(6);
Expand Down
9 changes: 7 additions & 2 deletions src/components/__tests__/SkillTree.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React from 'react';
import { render, fireEvent, act } from '@testing-library/react';
import SkillTree from '../SkillTree';
import MockLocalStorage from '../__mocks__/mockLocalStorage';
import { SkillProvider } from '../../context/SkillContext';
import { SkillProvider } from '../../context/SkillAppContext';
import SkillTreeGroup from '../../components/SkillTreeGroup';
import { SkillTreeProvider } from '../../context/SkillTreeContext';

const mockSkillTreeData = [
{
Expand Down Expand Up @@ -56,7 +57,11 @@ function renderComponent() {
{treeData => {
selectedSkillCount = treeData.selectedSkillCount;
resetSkills = treeData.resetSkills;
return <SkillTree title="borderlands" data={mockSkillTreeData} />;
return (
<SkillTreeProvider treeId="hey">
<SkillTree title="borderlands" data={mockSkillTreeData} />
</SkillTreeProvider>
);
}}
</SkillTreeGroup>
</SkillProvider>
Expand Down
86 changes: 43 additions & 43 deletions src/context/SkillContext.tsx → src/context/SkillAppContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { ContextStorage, NodeState } from '../models';
import { Dictionary } from '../models/utils';
import { SELECTED_STATE } from '../components/constants';
// import { SELECTED_STATE } from '../components/constants';

type Props = typeof SkillProvider.defaultProps & {
appId: string;
Expand All @@ -11,33 +11,35 @@ type DefaultProps = {
storage: ContextStorage;
};

type Skills = Dictionary<NodeState>;

interface State {
skills: Skills;
globalSkills: Dictionary<Skills>;
skillCount: number;
selectedSkillCount: number;
}

export interface ISkillContext {
skills: Skills;
export interface ISkillAppContext {
appId: string;
skillCount: number;
selectedSkillCount: number;
updateSkillState: (key: string, updatedState: NodeState) => void;
updateSkillState: (treeId: string, updatedState: Skills) => void;
incrementSelectedSkillCount: VoidFunction;
decrementSelectedSkillCount: VoidFunction;
addToSkillCount: (number: number) => void;
addToSelectedSkillCount: (number: number) => void;
resetSkills: VoidFunction;
}

type Skills = Dictionary<NodeState>;

const SkillContext = React.createContext<ISkillContext>({
skills: {},
const SkillAppContext = React.createContext<ISkillAppContext>({
appId: '',
skillCount: 0,
selectedSkillCount: 0,
updateSkillState: () => undefined,
incrementSelectedSkillCount: () => undefined,
decrementSelectedSkillCount: () => undefined,
addToSkillCount: () => undefined,
addToSelectedSkillCount: () => undefined,
resetSkills: () => undefined,
});

Expand All @@ -49,20 +51,12 @@ export class SkillProvider extends React.Component<Props, State> {
constructor(props: Props) {
super(props);

const storedSkills: Skills =
const storedSkills: Dictionary<Skills> =
JSON.parse(props.storage.getItem(`skills-${props.appId}`)!) || {};

const selectedSkillCount = Object.keys(storedSkills).reduce((acc, i) => {
if (storedSkills[i] === SELECTED_STATE) {
return acc + 1;
}

return acc;
}, 0);

this.state = {
selectedSkillCount,
skills: storedSkills,
selectedSkillCount: 0,
globalSkills: storedSkills,
skillCount: 0,
};
}
Expand All @@ -75,12 +69,19 @@ export class SkillProvider extends React.Component<Props, State> {
window.removeEventListener('beforeunload', this.writeToStorage);
}

// refactor the increment items to use just one method.
addToSkillCount = (number: number): void => {
this.setState(({ skillCount }) => ({
skillCount: skillCount + number,
}));
};

addToSelectedSkillCount = (number: number): void => {
this.setState(({ selectedSkillCount }) => ({
selectedSkillCount: selectedSkillCount + number,
}));
};

incrementSelectedSkillCount = (): void => {
return this.setState(({ selectedSkillCount }) => {
return {
Expand All @@ -98,49 +99,48 @@ export class SkillProvider extends React.Component<Props, State> {
};

resetSkills = () => {
return this.setState(prevState => {
const { skills } = prevState;
let resettedSkills = { ...skills };
const skillKeys = Object.keys(resettedSkills);

skillKeys.map(key => {
resettedSkills[key] = 'locked';
});

return {
skills: resettedSkills,
selectedSkillCount: 0,
};
});
// return this.setState(prevState => {
// const { globalSkills } = prevState;
// let resettedSkills = { ...globalSkills };
// const skillKeys = Object.keys(resettedSkills);
// skillKeys.map(key => {
// resettedSkills[key] = 'locked';
// });
// return {
// skills: resettedSkills,
// selectedSkillCount: 0,
// };
// });
};

updateSkillState = (key: string, updatedState: NodeState): void => {
updateSkillState = (treeId: string, updatedState: Skills): void => {
this.setState((prevState: State) => {
const updatedSkills = {
...prevState.skills,
[key]: updatedState,
...prevState.globalSkills,
[treeId]: updatedState,
};

return {
skills: updatedSkills,
globalSkills: updatedSkills,
};
});
};

writeToStorage = () => {
this.props.storage.setItem(
`skills-${this.props.appId}`,
JSON.stringify(this.state.skills)
JSON.stringify(this.state.globalSkills)
);
};

render() {
return (
<SkillContext.Provider
<SkillAppContext.Provider
value={{
skills: this.state.skills,
appId: this.props.appId,
updateSkillState: this.updateSkillState,
addToSkillCount: this.addToSkillCount,
addToSelectedSkillCount: this.addToSelectedSkillCount,
skillCount: this.state.skillCount,
incrementSelectedSkillCount: this.incrementSelectedSkillCount,
decrementSelectedSkillCount: this.decrementSelectedSkillCount,
Expand All @@ -149,9 +149,9 @@ export class SkillProvider extends React.Component<Props, State> {
}}
>
{this.props.children}
</SkillContext.Provider>
</SkillAppContext.Provider>
);
}
}

export default SkillContext;
export default SkillAppContext;
Loading

0 comments on commit a471cd0

Please sign in to comment.