Created
February 17, 2019 04:04
-
-
Save Youngestdev/cc5e487fc7f10b1f25957ab54990a922 to your computer and use it in GitHub Desktop.
Converting from class to functional.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, {useEffect, useRef } from 'react'; | |
| import Rough from 'roughjs/dist/rough.umd'; | |
| import useForceUpdate from 'use-force-update'; | |
| const RoughContext = React.createContext(); | |
| const __VALID_KEYS__ = [ | |
| 'bowing', | |
| 'fill', | |
| 'fillStyle', | |
| 'fillWeight', | |
| 'hachureAngle', | |
| 'hachureGap', | |
| 'height', | |
| 'width', | |
| 'roughness', | |
| 'stroke', | |
| 'strokeWidth' | |
| ]; | |
| export const NodeMounter = props => { | |
| const ref = useRef(''); | |
| const { node } = props; | |
| ref.appendChild(node); | |
| useEffect(() => { | |
| //Perhaps there's something fishy here ? | |
| ref.current.removeChild(node); | |
| ref.current.appendChild(node); | |
| return () => { | |
| const { node } = props; | |
| ref.current.removeChild(node); | |
| } | |
| }, []); | |
| return <g ref={ref} />; | |
| }; | |
| const RoughConsumer = ({ type, dataString, points, ...data }) => ( | |
| <RoughContext.Consumer> | |
| {contextValue => { | |
| if (typeof contextValue === 'undefined') { | |
| throw new Error('ReactRough Component not found!'); | |
| } | |
| const dataArray = Object.keys(data); | |
| for (let i = 0, len = dataArray.length; i < len; i++) { | |
| if (!__VALID_KEYS__.includes(dataArray[i])) { | |
| throw new Error( | |
| `Invalid key "${dataArray[i]}" assigned to "${type} component"` | |
| ); | |
| } | |
| } | |
| let node = null; | |
| if (contextValue.rc) { | |
| if (type === 'path') { | |
| if (typeof points !== 'undefined') { | |
| throw new Error( | |
| 'You need a dataString property for path, not points' | |
| ); | |
| } | |
| node = contextValue.rc[type](dataString, data); | |
| } else { | |
| node = contextValue.rc[type](...points, data); | |
| } | |
| return contextValue.renderer === 'svg' ? ( | |
| <NodeMounter node={node} /> | |
| ) : null; | |
| } | |
| return null; | |
| }} | |
| </RoughContext.Consumer> | |
| ); | |
| export const Arc = props => <RoughConsumer type="arc" {...props} />; | |
| export const Circle = props => <RoughConsumer type="circle" {...props} />; | |
| export const Curve = props => <RoughConsumer type="curve" {...props} />; | |
| export const Ellipse = props => <RoughConsumer type="ellipse" {...props} />; | |
| export const Line = props => <RoughConsumer type="line" {...props} />; | |
| export const Path = props => <RoughConsumer type="path" {...props} />; | |
| export const LinearPath = props => ( | |
| <RoughConsumer type="linearPath" {...props} /> | |
| ); | |
| export const Polygon = props => <RoughConsumer type="polygon" {...props} />; | |
| export const Rectangle = props => <RoughConsumer type="rectangle" {...props} />; | |
| const ReactRough = props => { | |
| const { renderer, width, height, backgroundColor } = props; | |
| const forceUpdate = useForceUpdate(); | |
| let ctx, rc; | |
| let rendererRef = useRef(''); | |
| useEffect(() => { | |
| const { renderer } = props; | |
| ctx = | |
| renderer === 'canvas' && rendererRef.current.getContext('2d'); | |
| rc = Rough[renderer](rendererRef.current); | |
| // TODO: this.forceUpdate(); | |
| forceUpdate(); | |
| }, []); | |
| const clearCanvas = () => { | |
| const { backgroundColor, width, height } = props; | |
| // If this is the first render the ctx will be null | |
| // It will be cleared later in the useEffect arc | |
| if ( !ctx ) { | |
| return; | |
| } | |
| if ( backgroundColor ) { | |
| ctx.save(); | |
| ctx.fillstyle = backgroundColor; | |
| ctx.fillRect(0, 0, width, height); | |
| ctx.restore(); | |
| } else { | |
| ctx.clearRect(0, 0, width, height); | |
| } | |
| }; | |
| const redraw = () => forceUpdate(); | |
| let children = props.children; | |
| const rendererOptions = { | |
| width, | |
| height | |
| }; | |
| // First clear the canvas in case of a new render. | |
| if ( renderer === 'canvas') { | |
| clearCanvas(); | |
| } else { | |
| rendererOptions.style = { backgroundColor }; | |
| } | |
| const Renderer = renderer; | |
| return( | |
| <RoughContext.Provider value={{ rc: rc, renderer }}> | |
| <Renderer {...rendererOptions} ref={rendererRef}> | |
| {children} | |
| </Renderer> | |
| </RoughContext.Provider> | |
| ); | |
| }; | |
| ReactRough.defaultProps = { | |
| width: 500, | |
| height: 500, | |
| renderer: 'canvas' | |
| }; | |
| export default ReactRough; |
Author
I'll be going to church now. Perhaps, later
Author
Oh ok.
I still don't have access to my laptop but I'm my phone anyways. I'm not sure we need use force-update. Did you see my chat with Dan and Kent yesterday?
I'll just paste what I wanted. One could force update like this.
We'll just make use of useState to achieve that. No need for an extra dependency
Author
Oh ok pretty nice. I'll remove the extra dependency. I actually thought of that aporocahc but was also thinking, create a state object we won't use ?. I think the useState approach is >>> tho if we look at build size etc
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SO 17 tests passed. The remaining four failed - 3 of them were issues with .prototype. They should be pretty easy to fix by an expert, I'm not stressing my brain. Perhaps, take a look @ooade ?