Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
react-bindings
Advanced tools
Data Bindings for React
A binding is a wrapper type that can be used to read, write, and observe changes in a source of truth.
This package provides an implementation of bindings that works well with React and React Native. It also provides a few convenient tools for working with these bindings.
In the following example, we demonstrate creating, reading, and updating a binding as well as observing it for changes in two ways:
useBindingEffect
, which triggers a callback whenever the associated bindings changeBindingsConsumer
, which runs a render function whenever the associated bindings changeimport React from 'react';
import { BindingsConsumer, useBinding, useBindingEffect } from 'react-bindings';
export const MyComponent = () => {
// Creating a binding, initialized with 0
const myBinding = useBinding(() => 0, { id: 'myBinding' });
// Getting and logging the value of the binding
console.log('myBinding', myBinding.get()); // myBinding 0
// Setting the value of the binding
myBinding.set(1);
console.log('myBinding', myBinding.get()); // myBinding 1
// Registering a callback that will be triggered anytime the binding changes, while this component is mounted.
// By default, these calls are debounced.
useBindingEffect({ myBinding }, ({ myBinding }) => {
console.log('myBinding', myBinding);
});
const onIncClick = () => myBinding.set(myBinding.get() + 1);
// The rendered component includes a portion that will be automatically rerendered whenever the binding changes.
// By default, these rerenders are debounced.
return (
<div>
myBinding:
<BindingsConsumer bindings={{ myBinding }}>{({ myBinding }) => myBinding}</BindingsConsumer>
<button onClick={onIncClick}>Increment</button>
</div>
);
};
Things become a lot more interesting when you start passing bindings around, including them in React contexts, and dealing with asynchronous updates.
Bindings provide some additional functionality by default, such as locking, and they're also extensible, as we'll see more later. But, be sure to check out the API docs for more complete details.
For cases where you want to observe but not modify, you can use the ReadonlyBinding
interface. This package also provides three specialized forms of readonly binding:
In the following example, we make a component that is updated with a new random number every second. It displays the number as well as whether or not the number is even.
import React, { useEffect } from 'react';
import { Binding, BindingsConsumer, useBinding, useDerivedBinding } from 'react-bindings';
const streamRandomNumbers = (binding: Binding<number>) => {
const next = () => {
binding.set(Math.floor(Math.random() * 100));
timeout = setTimeout(next, 1000);
};
let timeout = setTimeout(next, 1000);
next();
return () => {
clearTimeout(timeout);
};
};
export const MyComponent = () => {
// Creating a binding initialized with 0
const myBinding = useBinding(() => 0, { id: 'myBinding', detectChanges: true });
// Creating a derived binding based on the evenness of myBinding's value
// These values are propagated in a debounced way by default
const isEven = useDerivedBinding({ myBinding }, ({ myBinding }) => myBinding % 2 === 0, { id: 'isEven' });
// Connecting to a function that will stream in a new random number every second, as long as this component is mounted
useEffect(() => {
const stop = streamRandomNumbers(myBinding);
return stop;
});
// The rendered component has two dynamically rendered portions, which will automatically be rerendered whenever their associated bindings
// change.
return (
<div>
<BindingsConsumer bindings={{ myBinding }}>{({ myBinding }) => myBinding}</BindingsConsumer>
is even:
<BindingsConsumer bindings={{ isEven }}>{({ isEven }) => (isEven ? 'true' : 'false')}</BindingsConsumer>
</div>
);
};
In the above example, we could have also chosen to set limitType: 'none'
on the isEven
derived binding, which would change the limiter from the default, which is 'debounce'
, so that propagation of changes from myBinding
to isEven
would happen immediately. However, it's generally better to only do that when it's critical that data be in sync because too many chained updates could lead to reduced frame rates and laggy user interactions.
To demonstrate binding extensibility, let's revise the above example so that the isEven
function is a property of myBinding
directly, instead of being a derived binding.
export const MyComponent = () => {
// Creating a binding initialized with 0 with an extra isEven field
const myBinding = useBinding(() => 0, {
id: 'myBinding',
detectChanges: true,
addFields: (b) => ({
isEven: () => b.get() % 2 === 0
})
});
// Connecting to a function that will stream in a new random number every second, as long as this component is mounted
useEffect(() => streamRandomNumbers(myBinding));
// The dynamic renderer use the binding directly instead of extracting the value and we're using the injected isEven function
return (
<div>
<BindingsConsumer bindings={myBinding}>
{() => (
<>
{myBinding.get()}
is even:
{myBinding.isEven() ? 'true' : 'false'}
</>
)}
</BindingsConsumer>
</div>
);
};
Thanks for checking it out. Feel free to create issues or otherwise provide feedback.
react-bindings is maintained by the team at Passfolio.
FAQs
Data bindings for React
The npm package react-bindings receives a total of 143 weekly downloads. As such, react-bindings popularity was classified as not popular.
We found that react-bindings demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.