Last active
July 14, 2020 06:41
-
-
Save trueadm/198ae6902d2c5459e91a8e571b561b40 to your computer and use it in GitHub Desktop.
This file contains 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
// Option C: | |
// this implementation has a small amount of overhead compared to (a) and (b) | |
const React = require('react'); | |
const counterState = React.createStateReducer({ | |
initialState: props => ({ | |
counter: 0, | |
divRef: React.createRef(), | |
}), | |
reducer: (action, state) => { | |
switch (action) { | |
case "INCREMENT": { | |
return React.updateState({counter: state.counter + 1}); | |
} | |
} | |
}, | |
didUpdate: (props, state) => { | |
state.divRef.style.color = props.color; | |
}, | |
}); | |
function CounterComponent(props) { | |
return counterState(props, (state, reduce) => | |
<div ref={state.divRef} onClick={() => reduce("INCREMENT"))}> | |
Count: {state.counter} | |
</div> | |
); | |
} | |
module.exports = CounterComponent; |
This file contains 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
// Option D: | |
// has the least overhead of all the implementations in Safari | |
const React = require('react'); | |
function initialState(props) ( | |
return { | |
counter: 0, | |
divRef: React.createRef(), | |
} | |
) | |
function reducer(action, state) ( | |
switch (action) { | |
case "INCREMENT": { | |
return React.updateState({counter: state.counter + 1}); | |
} | |
} | |
) | |
function didUpdate(props, state) { | |
state.divRef.style.color = props.color; | |
} | |
function CounterComponent(props) { | |
return React.createStateReducer( | |
{props, initialState, reducer, didUpdate}, | |
(state, reduce) => ( | |
<div ref={state.divRef} onClick={() => reduce("INCREMENT"))}> | |
Count: {state.counter} | |
</div> | |
) | |
); | |
} | |
module.exports = CounterComponent; |
This file contains 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
// Option E: | |
// has the least overhead of all the implementations in Chrome/Node/Firefox | |
const React = require('react'); | |
const CounterComponent = { | |
initialState(props) { | |
return { | |
counter: 0, | |
divRef: React.createRef(), | |
} | |
}, | |
reducer(action, state) ( | |
switch (action) { | |
case "INCREMENT": { | |
return React.updateState({counter: state.counter + 1}); | |
} | |
}, | |
didUpdate(props, state) { | |
state.divRef.style.color = props.color; | |
}, | |
render(props, state, reduce) { | |
return ( | |
<div ref={state.divRef} onClick={() => reduce("INCREMENT"))}> | |
Count: {state.counter} | |
</div> | |
); | |
} | |
} | |
module.exports = CounterComponent; |
This file contains 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
// Option A: | |
// this implementation has quite a bit of overhead in all browsers due to the | |
// function creation in the functional component | |
const React = require('react'); | |
const counterState = React.createState(); | |
const counterReducer = (action, state) => { | |
switch (action) { | |
case "INCREMENT": { | |
return React.updateState({counter: state.counter + 1}); | |
} | |
} | |
}; | |
function CounterComponent(props) { | |
return counterState({ | |
initialState: () => ({ | |
counter: 0, | |
divRef: React.createRef(), | |
}), | |
didUpdate: state => { | |
state.divRef.style.color = props.color; | |
}, | |
reducer: counterReducer, | |
render(state, reduce) { | |
return ( | |
<div ref={state.divRef} onClick={() => reduce("INCREMENT"))}> | |
Count: {state.counter} | |
</div> | |
); | |
} | |
}); | |
} | |
module.exports = CounterComponent; |
This file contains 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
// Option B: | |
// this implementation has quite a bit of overhead in all browsers due to the | |
// function creation in the functional component | |
const React = require('react'); | |
const counterState = React.createStateReducer((action, state) => { | |
switch (action) { | |
case "INCREMENT": { | |
return React.updateState({counter: state.counter + 1}); | |
} | |
} | |
}); | |
function CounterComponent(props) { | |
return counterState({ | |
initialState: () => ({ | |
counter: 0, | |
divRef: React.createRef(), | |
}), | |
didUpdate: state => { | |
state.divRef.style.color = props.color; | |
}, | |
render(state, reduce) { | |
return ( | |
<div ref={state.divRef} onClick={() => reduce("INCREMENT"))}> | |
Count: {state.counter} | |
</div> | |
); | |
} | |
}); | |
} | |
module.exports = CounterComponent; |
@bvaughn I've updated example E after speaking with Dan. I think example A and B are probably going to be no goes because of the overhead they add in the render phase. The naming of createState()
was also probably not the right name for this method.
The reason I went with different lifecycle names was purely to avoid confusion with existing ones – as the arguments passed wouldn't match up. I'm not fussed on name, I just didn't want to create more confusion. We could also infer async by default with some of them, to help the async story more (rather than sync like they are now).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Disclaimer: I'm super jet-lagged and my brain is only half working at the moment, but since Dom asked me to take a look- I think I like option-e the best. 😄
I do have a thought or two:
React.createState
returns a function instead of a state? Doesn't seem obvious why that's necessary since it doesn't accept any arguments. Is it just to make it more comparable to the others?CounterComponent
function even need to exist? All it does is relay props. Could reduce boilerplate a little with just:I'd also like to learn a little more about the constraints of
didUpdate
. What types of things- other than tweaking refs- is it okay to do in this lifecycle? (Is there anything that's safe to do in egcomponentDidMount
that it won't be safe to do indidUpdate
without causing deopts?)