npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-databinding

v1.1.1

Published

react-databinding

Downloads

9

Readme

react-databinding

Travis build status NPM version

As we know , the two-way binding is general feature in Angular & Vue.js but not supported in React. So we have to write down much code to handle the technical issue not focus on the business, react-databinding is used to make it easier.

Goal

  • Easy to understand and simple to use
  • Two level designed APIs
    • Top level for Component#render() (one-way & two-way binding)
    • Lower level for functional programming ( Functor & Monad )
  • The value can be evaluated by path expression
  • Easy to customize the behaviour if the target component is changed

Get started

install

> npm install react-databinding --save

by manual vs. decorator

There are two styles to do data binding in react-databinding.

style | import ---|--- by manual | import {oneWayBind, twoWayBind} from 'react-databinding/react-data-bind' with decorator | import {oneWayBind, twoWayBind} from 'react-databinding/react-decorator'

Here we show the different between the two styles of data binding , we choose one-way binding for example , the two-way binding is similar .

import {oneWayBind, twoWayBind} from 'react-databinding/react-data-bind';

//by manual
class SampleComponent extends React.Component {

	render() {
		let $ = oneWayBind(this.props);
		return (<div>
			<h1>{$('data.title')}</h1>
		</div>)
	}

}
import {oneWayBind, twoWayBind} from 'react-databinding/react-decorator';

//with decorator
class SampleComponent extends React.Component {

	@oneWayBind()
	render($) {
		return (<div>
			<h1>{$('data.title')}</h1>
		</div>)
	}

}

If you choose the style of decorator, remember pass the binding operation ($ in our example) to the render function.

one-way & two-way binding

There are many solutions to implement one-way or two-way binding in React world , but we like more simple and less coding API if we use it in the render() function.

Here we will show how to get the easiest to understand and simplest to use one-way and two-way data binding in React Component.

case 1: one-way binding

First, let's prepare the container Component to create a component and pass something as props to it.

const data = {
	title:'hello world',
	body:'blablablabla...'
}

const ContainerComponent = () => (
	<ImmutableComponent data={data}/>
)

Then goes to the ImmutableComponent which we will show the one-way binding

import {React} from 'react';
import {oneWayBind} from 'react-databinding';

class ImmutableComponent extends React.Component {

	render() {
		// $ is curried function and please feel free to rename it in your project.
		let $ = oneWayBind(this.props);
		// 'hello world' will be shown as the h1 title
		return (
			<div><h1>{$('data.title')}</h1></div>
		);
	}

}

Nothing special, just one more line to create a curried $ function which will do the left work in the JSX part.

As you see, it's quite simple to do one-way binding , the magic is $ function , it accept the path ('data.title') and evaluate based on the Component's props.

One more thing, the $ function can accept a default value or a lambda callback which will be very useful if you want to handle the null eval result.

const todolist = [{
	title: 'complete the readme before this weekend' ,
	tags: ['help','doc'],
	status: 'pending'
}];

Show 'unknown' if the author not defined in todo

$('todolist.0.author','unknown')

Show comma-joined tags

$('todolist.0.tags', v => v ? v.join(','):'unknown')

As you see, complex path is supported, the array index is taken as the key of object , please feel free to try it out.

case 2: two-way binding

The two-way binding is a bit different but similar. Here we use $$ to indicate it's a two-way binding.

First, let's prepare the container Component to create a component and pass something as props to it.

const data = {
	username:'react-databinding',
	nickname:'two-way binding'
}

const ContainerComponent = () => (
	<MutableComponent user={data}/>
)

Then goes to the MutableComponent which we will show the two-way binding.


class MutableComponent extends React.Component {

	constructor(props, context) {
		super(props, context);
		let { user } = props;
		this.state = {user};
	}

	render() {
		let $$ = twoWayBind(this);
		return (
			<div>
				<input id="username" type="text" {...$$('user.username')}/>
				<input id="nickname" type="text" {...$$('user.password')}/>
			</div>
		);
	}

}

In the render() function , the $$ returns a composed object, so we use the ... to expand as the input's props.

immutable-js

Of course, the important immutable-js is supported.

We try to keep the general API and immutable supported API in the same , the only different is the import part.

//general
import {oneWayBind,twoWayBind} from 'react-databinding';

//immutable
import {oneWayBind,twoWayBind} from 'react-databinding/immutable';

//decorator
import {oneWayBind,twoWayBind} from 'react-databinding/immutable/react-decorator';

How it works

But how it works , what is working on the backend. Let's show more example to explain it.

First, import the react-databinding

import { F } from 'react-databinding';

Now let's prepare the data to show the usage

const data = [
	{
		calories: {total: 0, fat: 0},
		vitamins: {a: {total: 0, retinol: 0}, b6: 0, c: 0},
		fats: {total: 0},
		minerals: {calcium: 0}
	},
	{
		calories: {total: 150, fat: 40},
		vitamins: {a: {total: 100}, b6: 30, c: 200},
		fats: {total: 3}
	},
	{
		calories: {total: 100, fat: 60},
		vitamins: {a: {total: 120, retinol: 10}, b6: 0, c: 200},
		minerals: {calcium: 20}
	}
];

case 1: iterate the data and get the value

before


let item = data[1];
if (item != null) {
	let fats = item.fats;
	if (fats != null) {
		let total = fats.total;//3
	}
}

after

import {F, Optional} from 'react-databinding';

F.of(data).at('1.fats.total').value();//3
//or
(new Optional(data)).at('1.fats.total').value();//3

case 2: convert the data

before


let item = data[1];
if (item != null) {
	let fats = item.fats;
	if (fats != null) {
		let total = fats.total;
		if (total != null) {
			total = total + 1; //4
		}
	}
}

after

import {F,Optional} from 'react-databinding';

F.of(data).at('1.fats.total').map(v -> v+1).value();//4
//or
(new Optional(data)).at('1.fats.total').map(v -> v+1).value();//4

immutable

Yes , immutable is supported as well. The APIs is designed exactly matched as previous, the different is import part.

import {F} from 'react-databinding/immutable';

And make sure the args you passed to F.of is an immutable object.

import { fromJS } from 'immutable';
import { F } from 'react-databinding/immutable';

let immutableData = fromJS(data);

F.of(immutableData).at('1.fats.total').map(v -> v+1).value();//4