
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
react-parm
Advanced tools
Handle react classes with more functional purity
react-parm
is a thin abstraction providing partial-application methods that allow you to handle react
classes with much more functional purity. This allows for better encapsulation, greater separation of concerns, and simplified testing. When combined with destructuring, it also improves readability and comprehension.
import React from "react";
import { createElementRef, createMethod } from "react-parm";
export const componentDidMount = ({ getFoo, props }) =>
props.shouldGetFoo && getFoo();
export const onClickGetBar = ({ getBar }, [event]) =>
getBar(event.currentTarget.dataset.baz);
export default class App extends React.Component {
// lifecycle methods
componentDidMount = createMethod(this, componentDidMount);
// refs
element = null;
// instance methods
onClickGetBar = createMethod(this, onClickGetBar);
render() {
return (
<button
data-baz="quz"
onClick={this.onClickGetBar}
ref={createElementRef(this, "element")}
>
Go get bar!
</button>
);
}
}
Create a functional instance or lifecycle method, which will receive the full instance as the first parameter.
createMethod(instance: ReactComponent, method: function, ...extraArgs: Array): (instance: ReactComponent, args: Array, extraArgs: Array) => any
import React from "react";
import { createMethod } from "react-parm";
export const componentDidMount = ({ setState }) =>
setState(() => ({ isMounted: true }));
export const onClickDoThing = ({ props }, [event], [withStuff]) =>
props.doThing(event.currentTarget, withStuff);
export default class App extends Component {
state = {
isMounted: false
};
componentDidMount = createMethod(this, componentDidMount);
onClickDoThing = createMethod(this, onClickDoThing, true);
render() {
return (
<div>
<h3>Welcome to doing the thing</h3>
<button onClick={this.onClickDoThing}>Do the thing</button>
</div>
);
}
}
Create a value to assign to the instance based on a functional method which will receive the full instance as the first parameter.
createValue(instance: ReactComponent, method: function, ...extraArgs: Array): any
import React from "react";
import { createValue } from "react-parm";
export const getLength = ({ props }) => {
return props.foo.length;
};
export default class App extends Component {
length = createValue(this, getLength);
render() {
return <div>The length of the foo parameter is {this.length}</div>;
}
}
Create a functional render method, which will receive the props
as the first parameter, and the full instance as the second parameter.
createRender(instance: ReactComponent, render: function): (props: Object, instance: ReactComponent) => ReactElement
import React from "react";
import { createMethod, createRender } from "react-parm";
export const componentDidMount = ({ setState }) =>
setState(() => ({ isMounted: true }));
export const DoTheThing = ({ doThing }, { state: { isMounted } }) => {
return (
<div>
<h3>Welcome to doing the mounted thing</h3>
<span>Am I mounted? {isMounted ? "YES!" : "No :("}</span>
<button onClick={doThing}>Do the thing</button>
</div>
);
};
export default class App extends Component {
state = {
isMounted: false
};
componentDidMount = createMethod(this, componentDidMount);
onClickDoThing = createMethod(this, onClickDoThing, true);
render = createRender(this, DoTheThing);
}
NOTE: The difference in signature from createMethod
is both for common-use purposes, but also because it allows linting tools to appropriately lint for PropTypes
.
Create a functional component with all available instance-based methods, values, and refs a Component
class has.
createComponent(render: function, options: Object): ReactComponent
import React from "react";
import { createComponent } from "react-parm";
export const state = {
isMounted: false
};
export const componentDidMount = ({ setState }) =>
setState(() => ({ isMounted: true }));
export const onClickDoThing = ({ props }, [event], [withStuff]) =>
props.doThing(event.currentTarget, withStuff);
export const DoTheThing = ({ doThing }, { onClickDoThing }) => (
<div>
<h3>Welcome to doing the thing</h3>
<button onClick={doThing && onClickDoThing}>Do the thing</button>
</div>
);
DoTheThing.displayName = "DoTheThing";
DoTheThing.propTypes = {
doThing: PropTypes.func.isRequired
};
export default createComponent(DoTheThing, {
componentDidMount,
onClickDoThing,
state
});
The component will be parmed with createRender
, all methods passed in options
will be parmed with createMethod
, and all other values will be assigned to the instance. There are also two additional properties that are treated outside the context of assignment to the instance:
isPure
=> should PureComponent
be used to construct the underlying component class instead of Component
(defaults to false
)getInitialState
=> if a method is passed, then it is parmed and used to derive the initial state instead of the static state
propertygetInitialValues
=> If a method is passed, then it is parmed and used to derive initial instance values
{foo: 'bar'}
will result in instance.foo
being "bar"
onConstruct
=> If a method is passed, then it is called with the instance as parameter at the end of constructionNOTE: Any additional static values / methods you apply to the render component will be re-assigned to the parmed component.
Create a method that will assign the Component requested to an instance value using a ref callback.
createComponentRef(instance: ReactComponent, ref: string): (component: HTMLElement | ReactComponent) => void
import React from "react";
import { createElementRef } from "react-parm";
export default class App extends Component {
component = null;
render() {
return (
<SomeOtherComponent ref={createComponentRef(this, "component")}>
We captured the component instance!
</SomeOtherComponent>
);
}
}
The ref
string value passed will be the key that will be used in the assignment to the instance
.
Create a method that will assign the DOM node of the component requested to an instance value using a ref callback.
createElementRef(instance: ReactComponent, ref: string): (component: HTMLElement | ReactComponent) => void
import React from "react";
import { createElementRef } from "react-parm";
export default class App extends Component {
element = null;
render() {
return (
<SomeOtherComponent ref={createElementRef(this, "element")}>
We found the DOM node!
</SomeOtherComponent>
);
}
}
The ref
string value passed will be the key that will be used in the assignment to the instance
.
Create a method that will assign both the DOM node of the component requested and the component itself to a namespaced instance value using a ref callback.
createCombinedRef(instance: ReactComponent, ref: string): (component: HTMLElement | ReactComponent) => void
import React from "react";
import { createCombinedRef } from "react-parm";
export default class App extends Component {
someOtherComponent = null;
render() {
return (
<SomeOtherComponent ref={createCombinedRef(this, "someOtherComponent")}>
I have the best of both worlds! this.someOtherComponent will look like "{component: SomeOtherComponent, element: div}".
</SomeOtherComponent>
);
}
}
The value assigned will be an object with component
and element
properties, which reflect the component and the DOM node for that component respectively. The ref
string value passed will be the key that will be used in the assignment to the instance
.
Create a custom PropTypes validation method.
createPropType(validator: function): (metadata: Object) => (Error|null)
import { createPropType } from "react-parm";
export const isFoo = createPropType(({ component, name, value }) =>
value === "foo"
? null
: new Error(
`The prop "${name}" is "${value}" in ${component}, when it should be "foo"!`
);
);
The full shape of the metadata
object passed to createPropType
:
{
component: string, // the name of the component
key: string, // the key that is being validated
name: string, // the name of the prop being validated
path: string, // the full path (if nested) of the key being validated
props: any, // the props object
value: any // the value of the prop passed
}
Please note that usage may result in different values for these keys, based on whether the custom prop type is used in arrayOf
/ objectOf
or not.
When used in arrayOf
or objectOf
:
key
represents the nested key being validatedname
represents the name of the prop that was passedpath
represents the full path being validatedExample:
const isArrayOfFoo = createPropType(
({ component, key, name, path, value }) => {
value === "foo"
? null
: new Error(
`The key "${key}" for prop "${name}" at path ${path} is "${value}" in ${component}, when it should be "foo"!`
);
}
);
...
<SomeComponent bar={['baz']}>
// The key "0" for prop "bar" at path "bar[0]" is "baz" in "SomeComponent", when it should be "foo"!
When the prop type is used in any context other than arrayOf
/ objectOf
, then key
, name
, and path
will all be the same value.
PARM is an acronym, standing for Partial-Application React Method. Also, why not parm? It's delicious.
Standard stuff, clone the repo and npm install
dependencies. The npm scripts available:
build
=> run rollup to build development and production dist
filesdev
=> run webpack dev server to run example app / playgroundlint
=> run ESLint against all files in the src
folderlint: fix
=> runs lint
with --fix
prepublish
=> runs prepublish:compile
when publishingprepublish:compile
=> run lint
, test:coverage
, transpile:lib
, transpile:es
, and build
test
=> run AVA test functions with NODE_ENV=test
test:coverage
=> run test
but with nyc
for coverage checkertest:watch
=> run test
, but with persistent watchertranspile:lib
=> run babel against all files in src
to create files in lib
transpile:es
=> run babel against all files in src
to create files in es
, preserving ES2015 modules (for
pkg.module
)2.3.0
createComponent
for re-assigning any static value / method applied to the source componentFAQs
Handle react classes with more functional purity
The npm package react-parm receives a total of 1,732 weekly downloads. As such, react-parm popularity was classified as popular.
We found that react-parm demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.