jsx-kit
v0.1.2
Published
Standard React Components For Efficient JSX Syntax. Inline and Render Props Tools.
Downloads
1
Maintainers
Readme
jsx - kit
Standard React Components For Efficient JSX Syntax. Inline and Render Props Tools. Can help clean up JSX and reduce the need to create individualized component classes.
Components:
Hook - A pure component that takes props for componentDidMount, componentWillUnmount, and onConstructor (since componentWillMount is deprecated) then returns its children as the view.
ExposeState - Takes props for all non deprecated lifecycle hooks and initialState.The child is required to be a function takes an object containing the state object, props object, and the setState method already bind to the class. (Render Props Syntax)
ExposeRef - Equivalent to Expose State, but also passes a ref object to the Render Props Syntax.
Clone - Passes props to all direct children
Flex - Sets up a flex- box container and wraps all children in flex - box items
Elements - Exposes Children as an array for Array tranformations within a callback prop (transform)
ForwardChildren - Exposes grandchildren (or any other level of children) as an array for Array tranformations within a callback prop (transform)
GETTING STARTED:
npm install jsx-kit
import { ExposeState, Clone, Flex, Hook, ExposeRef } from ‘react-kit’
USE CASES:
ExposeState - Example reads “Hello World" then changes state to read “Goodbye World" when clicked.
<ExposeState initialState={{text:"Hello"}}>
{ ({ state, setState })=>{
let onClick=()=>setState({text:"Goodbye"})
return <p onClick={onClick}>{state.text+" World"}</p>
}
}
</ExposeState>
ExposeState also has callback props for all lifecycle methods.The callbacks do not take the same form of argument because the props and state objects need to additional be passed to the callback, but all arguments are still available on the arg object.
<ExposeState
initialState={{text:"Hello"}}
componentDidUpdate={ ({ props, state, prevProps, prevState })=>{
console.log(prevState)
console.log(state)
}
}
>
{ ({ state, setState })=>{
let onClick=()=>setState({text:"Goodbye"})
return <p onClick={onClick}>{state.text+" World"}</p>
}
}
</ExposeState>
ExposeRef - Example places focus on the input when the component mounts.
<ExposeRef componentDidMount={({ref})=>ref&&ref.current.focus()} >
{ ({ ref })=><input ref={ref} /> }
</ExposeRef>
The ExposeRef component also has state and all lifecycle methods.
Hook - Example console logs during lifecycle hooks
<Hook
onConstructor={({props})=>console.log("About to mount child with props")}
componentDidMount={({props})=>{
console.log("Mounted with props");
console.log(props);
}}
componentWillUnmount={({props})=>console.log("About to unmounted with props")}
>
<p>Any Random Component</p>
</Hook>
The hook component provides pure component class functionality for stateless components. All lifecycle hook callbacks provide an object with props as a property for an argument to expose them to the lifecycle hooks as would be available in class creation. So remember to deconstruct the argument object.
Clone - The example passes down state and theme as a prop to all direct children.
let state = {…
let theme = {…
return (
<Clone state={state} theme={theme}>
<Header />
<Body />
<Footer />
<Modal />
</Clone>
)
When there are single children, it is more concise use to React.clone or add props to elements normally.
verbose example:
Define a few components
const Text =props=>{
return <p>{props.text}</p>
}
const Text1 = props=>Text(props)
const Text2 = props=>Text(props)
Now lets use the props extract
<Clone text="Type:" propsExtractor={(entry, index, props)=>({text:props.text+entry.type.name+" index:"+index})} >
<Text />
<Text1 />
<Text2 />
</Clone>
HTML output:
Type:Text index:0
Type:Text1 index:1
Type:Text2 index:2
Flex - The example wraps the children all in a flex- box container and individually in a flex- box item.
<Flex justifyContent="space-between" >
<p>item 0</p>
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
<p>item 4</p>
</Flex>
verbose example:
<Flex
justifyContent="space-around"
containerStyle={{backgroundColor:"yellow"}} //all flex-box css properties are available on props
childrenStyle={{border:"5px solid black"}} //all children
itemStyle={ [ {textDecoration:"underline"}, {textDecoration:"none"} ] }//array of styles
keyExtractor={ (item, key)=>key }
styleExtractor={ (item, key, prevStyle, props)=>key%2?{...prevStyle, backgroundColor:"grey"}:{...prevStyle, backgroundColor:"white"} }//Alternate colors
>
<p>item 0</p>
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
<p>item 4</p>
</Flex>
Elements - Use the Elements component to gain Array functionality on the child React elements; such as switching (with find), mapping, filter, ect.
Switching:
<Elements tranform={(elements, props)=>elements.find(el=>el.key===state.page)}>
<Landing key="landing"/>
<Home key="home"/>
<About key="about"/>
<Contact key="contact"/>
</Elements>
Display States:
<Elements transform={array=>array.filter(el=>el.props.displayStates.includes(state.displayState))} >
<Header displayStates={["landing","home","contact","about"]} />
<Nav displayStates={["home","contact","about"]} />
<Greeting displayStates={["landing"]} />
<About displayStates={["about"]} />
<Contact displayStates={["contact"]} />
<Home displayStates={["home"]} />
<Footer displayStates={["home","contact","about"]} />
</Elements>
ForwardChildren - ForwardChildren transforms children with a transform callback just like in the Elements component, but the children can be nested in child elements.
Motivation: Some elements may require multiple parent operations take the example below.
We need to pass props to elements already wrapped in a Flex element, neither of the bellow will both make the elements red and wrap each element in it's own item div for flex-box:
<Clone style={{color:"red"}}>
<Flex justifyContent="space-between" >
<p>item 0</p>
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
<p>item 4</p>
</Flex>
</Clone>
Injected props on flex!
<Flex justifyContent="space-between" >
<Clone style={{color:"red"}}>
<p>item 0</p>
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
<p>item 4</p>
</Clone>
</Flex>
Wrapped Clone element in single flex item!
The solution is to use ForwardChildren
<ForwardChildren transform={ array=>array.map(child=>React.cloneElement(child, {style:{color:"red"}}) ) }>
<Flex justifyContent="space-between" >
<p>item 0</p>
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
<p>item 4</p>
</Flex>
</ForwardChildren>
There also exists a prop "level" with a default of 1 that can scope children deeper in the React element tree. (Does not handle branching!) if the level is set to 0 the ForwardChildren component becomes equivalent to the Elements component.