react-anaconda 🐍
Conditionally wrap react components and implicitly share props amongst children.
Rationale
Sometimes, you need to conditionally wrap a react component. This can be useful for tooltips, coachmarks and links/anchor tags, as well as for higher order component or render prop patterns.
When we need to wrap a react component conditionally we usually do something like the following inside our render
method:
const child = <i className='cool-icon'> Hello! </i>; if thispropslink return <a href=thispropslink> child </a> ; return child;
react-anaconda is a tiny (515 bytes) library with utilities for:
- conditionally wrapping react components
- Implicit prop sharing across children
Using react-anaconda, we could rewrite the previous example like this:
; return <Anaconda when=thispropslink wrap= <a href=thispropslink>children</a> > <i className='cool-icon'> Hello! </i> </Anaconda>
This is the most basic example. react-anaconda also works with lists and conditional wrapping based on child props. Check out the examples for more.
Installation
npm
npm i react-anaconda
yarn
yarn add react-anaconda
Examples
Wrap all children with a wrapper component based on a boolean value
Component
;; { return <Anaconda when=thispropsclickable wrap= <a href="http://cool-url.com">children</a> > <span> Click me! </span> <span> And me! </span> <span> Me Three! </span> <span> Me Four! </span> </Anaconda> } ReactDOM;
Rendered Markup
Click me! And me! Me Three! Me Four!
Wrap all mapped children with a wrapper component based on a boolean value
Component
;;; { return <Anaconda when=thispropsclickable wrap= <a href="http://cool-url.com">children</a> > thispropslinkNames </Anaconda> } ReactDOM;
Rendered Markup
Click me! And me! Me Three! Me Four!
Wrap children with a wrapper component if their props match a predicate
When you pass a function to the when
prop, react-anaconda will check the actual props of each child against that function. If the predicate is true, that child will be wrapped. Consider the following (slightly contrived) example.
Component
;;; { return <Anaconda when= propsnumPeople > 1 wrap= <div className="moreThanOne">children</div> > thispropsbookings </Anaconda> } ReactDOM;
Note this also works with normal children that aren't mapped. This is useful if you have a few different types of elements you want to conditionally wrap. Also notice how the second argument of wrap
will receive the child props so you can use them in your wrapper.
Component
;;; { return <Anaconda when= propslink wrap= <a href=propslink>children</a> > <span link="http://cool-url.com">Span</span> <button link="http://other-cool-url.com">Button</span> <article>Article</span> </Anaconda> } ReactDOM;
Rendered Markup
Span Button Article
Spread custom props implicitly across child components
Any props that you pass to react-anaconda apart from the when
and wrap
components will be shared amongst all children. Consider the following:
Component
;;; const NameBar = <span>name:bar</span>; const BarName = <span>bar:name</span>; { return <Anaconda when=thispropsclickable wrap= <a href="http://cool-url.com">children</a> name="foo" bar=5 > /* All these children will receive the name and bar props */ <NameBar clickable /> <BarName /> </Anaconda> } ReactDOM;
Rendered Markup
foo:55:foo
API
When
Boolean | (props: Object) => Boolean
-
The when prop can either be a boolean or a function.
-
If a boolean is passed and is true, children will be wrapped.
-
You can also pass a function to the
when
prop. This function will be used as a predicate and passed each childs props as an argument. If the childs props match the predicate, that child will be wrapped.
Wrap
(children: JSX.Element, props: Object) => JSX.Element
- Wrap is a render prop allowing which has 2 arguments.
- The first
children
argument is the component that will be wrapped. - The second
props
argument is the props of the component to be wrapped as an object. - You should return JSX from this function.
Development
Clone the repo and install dependencies with your favourite package manager. The NPM scripts in the package.json
are below.
build
=> builds and minifies the code and outputs a production ready bundleclean
=> blows away build folders (es
,dist
) for a clean builddev
=> runs aparcel
development server with hot reloading for development. Access the development playground atlocalhost:1234
prepublishOnly
=> runsprepublish:compile
when executing anpm publish
prepublish:compile
=> runtest
,clean
thenbuild
test
=> runs the jest test suite.test:watch
=> runtest
inwatch
mode, which will re-run when you change files pertaining to your tests.contributors:add
=> add a contributor to the all-contributorsrc. For example:npm run contributors:add -- yourusername
. You can then select your contributions.contributors:generate
=> generate the new allcontributors file before checking in.contributors:check
=> check that the all-contributorsrc reflects all the people who have actually contributed to the project on github.
Contributors
Thanks goes to these wonderful people (emoji key):
Martin McKeaveney 💻 📖 💡 🤔 🚇 ⚠️ |
Daniel Skelton 💻 ⚠️ |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!