
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
an arbitrary magic react state management for rxjs enthusiast.
npm i meng --save
众所周知,react是一个侧重同步数据到dom的库,也就是(data) => dom
. 这里的data包含了props
和state
,但是其他的数据源不好管理,比如说api。
而现有的方案用起来都太复杂了,本来(data) => dom
一个函数能解决的问题,用了flux架构比如redux之后,需要的模块*3。所以能不能用一种简单的方式把所有数据源都抽象成data
,
并且能用react的方式解决问题呢,答案是肯定的,我们可以这么设计({props, state, api}) => dom
。于是就有了meng--一个把所有数据源都抽象合并成一种数据类型的库。
由于只有rxjs能帮我们实现流的特性,所以meng@3.x是强依赖rxjs的。
每一个meng组件都有自己的store,store的结构是这样的:
interface Store<S> {
state$: ReplaySubject<S> // store的触发器
store$: Observable<S> // store的状态容器
children: { [key: string]: Store<Object> } //存放子store,因为是扁平结构,所以只有根store的children才有子节点
setState: Function, // 设置store$的状态
subscribe: (success: (state: Object) => void, error?: (error: Error) => void, complete?: () => void) => Subscription // 订阅store$
}
所有的meng组件的状态又都会放在根节点的children里面,所以meng支持直接修改和订阅另一个组件的状态。也可以把store想象成ng的rootScope, 而children里面的store相当于ng里controller对应的scope。下面是一段demo:
import Store from 'meng'
Store.children.App.setState({user: {name: "corol"}}, error => {})
lift函数可以把react组件提升为meng组件,他只有两个参数:
initialState
初始化meng组件的状态initialName
设置store的名字,如果不显式的设置,则默认使用displayName、函数名称、随机一个名字,按优先级排序。Resource
给组件注入数据源,可以是promise,也可以是其他组件的store,也可以是函数。如果是函数,则第一个参数是 initialState,包括父级传下来的属性。selector
注入到react组件的props的变量的名称,可以是stirng也可以是返回一个对象(会覆盖store里的其他状态)可以监听 lift 里面的状态和其他 injected 数据源. 从3.4.0开始,也可以监听自己和其他 listen 数据源了,所以要判断好循环边界哦.
在 meng 把状态提升之后,状态不在只是 Object 了,它现在是 Maybe(Observable),有可能会失败。输出成功的结果到组件,输出错误的结果到这个 errorhandler 里. 如果出错且没有注册 error,则什么事情都不会发生。如果已经注册,则调用它。注意,如果是通过 setState 传进去一个错误的 Observable 进去的话,只能在 setState 的 callback 捕获到异常信息
展示一段我用meng写的博客里的代码吧:
const listenList = (currentStore: Props, nextStore: Props) => {
return currentStore.latest !== nextStore.latest ? list("C0PKC07FB", nextStore.latest) : null
}
const listSelector = (currentState: Props, state: ISlackListType) => {
const previousMessages = (currentState.post && currentState.post.messages) || []
state.messages = previousMessages.concat(state.messages)
return { post: state }
}
@inject(connect, "newmsg")
@listen(listenList, listSelector)
@inject(user, "user")
@lift({ latest: "0", newmsg: [] as Array<ISlackUserMessage & ISlackBotMessage> }, "Slack")
export default class Slack extends React.Component<Props, void> {
public render() {
return (
<div className={Style.SLACK}>
<Title />
<TextInput />
<Flex flexGrow={1} flexDirection={"row"}>
<Messages newmsg={this.props.newmsg} post={this.props.post} user={this.props.user} latest={this.props.latest} />
<Users user={this.props.user} />
</Flex>
</div>
)
}
}
详细信息请移步我的博客
因为inject可以接受并订阅你的任意类型数据,所以你可以随意组合你的数据源,也可以组合成高阶数据源(依赖其他数据源的数据源),并把他们作为你视图的数据层。
//组合数据源
didmount() {
fetch("xxx")
.then(x => fetch("yyy"))
.then(yyy => this.setState({yyy}))
}
//数据源订阅数据源
didmount() {
fetch("xxx")
.then(xxx => {
this.setState({xxx})
return fetch("yyy")
})
.then(yyy => this.setState({yyy}))
}
//商品详情 url: xxx/:pid
componentReceiveProps(nextProps) {
if (this.props.pid !== nextProps.pid) getById(pid).then(data => this.setState({data}))
}
componentDidMount() {
getById(pid).then(data => this.setState({data}))
}
//websocket
didmount() {
this.ws = new Websocket(url)
ws.onmessage = (message) => {
this.setState(message)
}
}
willUnmount() {
ws.close()
}
mengbi.jsÏ
//组合数据源
@inject(() => fetch(xxx).then(xxx => fetch(yyy)), "yyy")
@lift({yyy: null})
//数据源订阅数据源
@inject((currentStore, nextStore) => currentStore.xxx !== nextStore.xxx ? fetch(yyy) : null, "yyy")
@inject(() => fetch(xxx), "xxx")
@lift({xxx: null, yyy: null})
//商品详情 url: xxx/:pid
@inject((currentStore, nextStore) => currentStore.pid !== nextStore.pid ? getById(nextStore.pid) : null, "data")
//websocket(rxjs)
@inject(() => Observable.webSocket(url), "message")Ï
Store.children.Dialog.setState({display: "open"})
就能打开这个对话框了因为meng是管理数据源为主,夸组件通讯为辅的。你可以像redux那样直接注入数据源,但是应该尽量避免让组件从其他地方获取数据,原则上组件获取数据的方式只有一个,就是父组件, 所有的数据源都应该从视图开始注入,然后传到下面的子组件,这是符合依赖倒置原则的。上面的示例就是一个正确的用法。
发现一款和我思路很像的库,强烈建议看看freactal 发现第二个和我思路很像的库,preact版本,可以说这个库的思路和我基本是完全一样了: wiretie
另附一篇我之前写的文章我为什么不用redux
FAQs
an high order component for lift state and inject data source
The npm package meng receives a total of 8 weekly downloads. As such, meng popularity was classified as not popular.
We found that meng 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.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.