Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfisher committed Jan 25, 2024
1 parent 1a4e551 commit 561f4b1
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 51 deletions.
8 changes: 7 additions & 1 deletion example/src/FormDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, useState } from "react";
import Card from "./components/Card"
import Network from './forms/network';
import JsonViewer from "./components/JsonViewer"
import { AsyncComputedObject } from "helux-store";
import { AsyncComputedObject, watch } from "helux-store";
import classnames from 'classnames';
import { ReactFC } from "./types";
import ColorBlock from "./components/ColorBlock";
Expand Down Expand Up @@ -60,6 +60,12 @@ const ValidResult:React.FC<React.PropsWithChildren<{validate: boolean | AsyncCom
</span>
}

watch((state)=>{
console.log("watch state change:",state)
},{
depends:()=>[Network.state]
})

const NetworkForm = ()=>{

return <Network.Form className="panel">
Expand Down
15 changes: 12 additions & 3 deletions example/src/forms/network.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { ComputedScopeRef, computed } from "helux-store";
import { Dict, createForm,action } from "speed-form";
import { ComputedScopeRef, Dict, computed } from "helux-store";
import { createForm,action } from "speed-form";
// import { Project, getProjects } from "../api/getProjects";
import { delay } from "flex-tools/async/delay";
import validator from "validator";
let count =1
// 声明表单数据
const formSchema = {
diary: computed<boolean>(()=>{
return true
},{depends:[]}),
fields: {
asyncTitle: {
value: "React-Helux-Form",
Expand Down Expand Up @@ -144,6 +147,9 @@ const formSchema = {
},
progressSubmit2: { // 这是一个动作,
title: "提交进度2",
validate:async ()=>{
return true
},
execute:action(async (fields,{getProgressbar})=>{
console.log("submit fields=",fields)
const bar = getProgressbar()
Expand Down Expand Up @@ -188,13 +194,16 @@ const formSchema = {
enable: (root: any) => {
return root.fields.wifi.ssid.value.length > 3
},
validate:computed<true>(async (root: any)=>{
return true
}),
execute: action(async (scope:any,{abortSignal}) => {
return new Promise<number>((resolve,reject)=>{
setTimeout(()=>{
resolve(count++)
},2000)
abortSignal()?.addEventListener("abort",()=>{
console.log("已取消cancelled")
console.log("已取消: cancelled")
reject("cancelled")
})
})
Expand Down
3 changes: 1 addition & 2 deletions packages/form/src/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@


import { ReactNode, useCallback,useState,useEffect, useRef, RefObject, useMemo} from "react";
import { Dict } from "./types";
import React from "react";
import type { FormOptions } from "./form";
import { AsyncComputedGetter, AsyncComputedObject, ComputedAsyncReturns, ComputedOptions, ComputedParams, IStore, RuntimeComputedOptions, computed, getValueByPath, watch } from 'helux-store';
import { AsyncComputedGetter, AsyncComputedObject, ComputedAsyncReturns, ComputedOptions, ComputedParams, Dict, IStore, RuntimeComputedOptions, computed, getValueByPath, watch } from 'helux-store';
import { omit } from "flex-tools/object/omit";
import { getFormData } from "./serialize";
import { getSnap } from "helux"
Expand Down
11 changes: 3 additions & 8 deletions packages/form/src/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
*/

import React, { useCallback } from "react";
import { type StoreSchema, createStore,RequiredComputedState, ComputedScopeRef, ComputedOptions, IStore, computed, AsyncComputedParams, AsyncComputedObject } from "helux-store";
import type { ReactFC, Dict, ComputedAttr } from "./types";
import { type StoreSchema, createStore,RequiredComputedState, ComputedScopeRef, ComputedOptions, IStore, computed, AsyncComputedParams, AsyncComputedObject, Dict } from "helux-store";
import type { ReactFC, ComputedAttr } from "./types";
import { FieldComponent, createFieldComponent } from './field';
import { FieldGroupComponent, createFieldGroupComponent } from "./fieldGroup";
import { assignObject } from "flex-tools/object/assignObject";
Expand Down Expand Up @@ -206,12 +206,7 @@ function setFormDefault(define:any){
}
}

/**
* 加载表单数据
*/
function loadFormData(store:any){

}

/**
* 我们约定,每一个动作均由一个{execute:computed(async ()=>{})}对象来描述
Expand Down Expand Up @@ -290,7 +285,7 @@ export function createForm<Schema extends Dict=Dict>(define: Schema,options?:For
fields:store.state.fields as FieldsType,
state:store.state as (typeof store.state) & RequiredComputedState<FormSchemaBase> & {actions:ActionsType},
useState:store.useState,
load:loadFormData

};
}

Expand Down
14 changes: 11 additions & 3 deletions packages/form/src/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*
*/

import { Dict } from "./types"
import { isPlainObject } from "flex-tools/typecheck/isPlainObject"
import type { Dict } from "helux-store"

function isFormAction(data:Dict){
return 'execute' in data && !isFieldValue(data)
Expand Down Expand Up @@ -46,8 +46,7 @@ function getFieldValue(data:Dict){

function getFiledGroupValue(data:Dict){
const result:Dict = {}
Object.entries(data).forEach(([key,value])=>{

Object.entries(data).forEach(([key,value])=>{
if(typeof(key) !== 'string'){
return
}
Expand Down Expand Up @@ -93,6 +92,15 @@ export function getFormData(snap:Dict,options?:GetFormDataOptions):Record<string
return getFiledGroupValue(snap)
}

/**
* 加载表单数据
*/
export function loadFormData(this:any,data:Dict){

}



export interface CreateFormDataOptions{
// 用来实现将keyPath转换为表单项名称
getItemName?:(keyPath:string[])=>string
Expand Down
4 changes: 1 addition & 3 deletions packages/form/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export type ReactFC<Props=unknown> = React.FC<React.PropsWithChildren<
Pick<React.HTMLAttributes<HTMLElement>,'className' | 'style'> & Props>>

export type FormData = Record<string, any>;

export type Dict<T=any> = Record<string,T> // 字段属性类型集



export type Primitive = number | boolean | string | null | undefined

Expand Down
4 changes: 2 additions & 2 deletions packages/store/src/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ function getComputedRefDraft(draft: any, params:{input:any[],type:'context' | 's
*/
export function computed<R = any,ExtraAttrs extends Dict = {}>( getter: AsyncComputedGetter<R>,depends?:ComputedDepends,options?: ComputedOptions<R,ExtraAttrs>): ComputedAsyncReturns<R & ExtraAttrs>;
export function computed<R = any,ExtraAttrs extends Dict = {}>( getter: ComputedGetter<R>, options?: ComputedOptions<R,ExtraAttrs>): R
export function computed<R = any,ExtraAttrs extends Dict = {}>( getter: any,depends:any, options?: ComputedOptions<R,ExtraAttrs>):any {
export function computed<R = any,ExtraAttrs extends Dict = {}>( getter: any,depends?:any, options?: ComputedOptions<R,ExtraAttrs>):any {

if (typeof getter != "function") throw new Error("getter must be a function");

Expand Down Expand Up @@ -571,7 +571,7 @@ function createAsyncComputedMutate<Store extends StoreSchema<any>>(stateCtx: ISh
}
}
},
// 此函数在依赖变化时执行,用来异步计算
// @ts-ignore 此函数在依赖变化时执行,用来异步计算
task: async ({ draft, setState, input, extraArgs }) => {
// 当使用run方法时可以传入参数来覆盖默认的计算函数的配置参数
const finalComputedOptions = Object.assign({},computedOptions,extraArgs) as Required<ComputedOptions>
Expand Down
16 changes: 8 additions & 8 deletions packages/store/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export type StateSetter<State,Value=any> = (state:State,value:Value)=>void
*
* @param useState
*/
function wrapperUseState<State extends Dict>(stateCtx:ISharedCtx<State["state"]>){
function useStateWrapper<State extends Dict>(stateCtx:ISharedCtx<State["state"]>){
return function<Value=any,SetValue=Value>(getter?:StateGetter<RequiredComputedState<State>,Value>,setter?:StateSetter<RequiredComputedState<State>,SetValue>){
const useState = stateCtx.useState
if(getter==undefined){
Expand Down Expand Up @@ -104,10 +104,10 @@ export interface StoreOptions{
}


export type IStore<State extends Dict=Dict> = ISharedCtx<State> & {
state:ISharedCtx<State>['reactive']
useState:ReturnType<typeof wrapperUseState>
computedObjects:Record<string,{run:()=>void}>
export type IStore<State extends Dict=Dict> = ISharedCtx<ComputedState<State>> & {
state:ISharedCtx<ComputedState<State>>['reactive']
useState:ReturnType<typeof useStateWrapper>
computedObjects:Record<string,{run:()=>void}>
}


Expand Down Expand Up @@ -137,15 +137,15 @@ export function createStore<T extends StoreSchema<any>>(data:T,options?:StoreOpt
createComputed<T['state']>(stateCtx,computedObjects,opts)!

// 3. 处理useState
const useState = wrapperUseState<T['state']>(stateCtx)

const useState = useStateWrapper<T['state']>(stateCtx)
return {
actions,
...stateCtx,
state:stateCtx.reactive,
useState,
computedObjects:{}
}
});
}) as IStore<T['state']>

}
6 changes: 3 additions & 3 deletions packages/store/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ export function getError(e:any):Error{
*/
export function getDeps(arg:ComputedDepends | undefined,ctx?:any):(string[])[]{
let deps:(string[])[]= []
if(typeof(arg) === 'function'){
arg = arg.call(ctx,ctx)
}
// if(typeof(arg) === 'function'){
// arg = arg.call(ctx,ctx)
// }
deps = (arg || []).map((d: any) =>Array.isArray(d) ? deps : d.split("."))
return deps
}
52 changes: 34 additions & 18 deletions packages/store/src/watch.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
/**
*
*
*
*
*
* const off = watch(()=>state.aa.bb.cc)
* off() // 取消监听
*
*
*
*/
import { watch as heluxWatch} from "helux";
import { watch as heluxWatch } from "helux";


export interface WatchOptions{
immediate?:boolean
immediate?:boolean
depends?:()=>any
// 指定额外的过滤条件,如果返回true,才会触发listener的执行
filter?:(valuePath:string[])=>boolean
}

export interface WatchResult{
off?:boolean
}

/**
* 用来监听状态的变化
* computed(()=>{},[])
* watch(()=>{
*
* },{
* depends:()=>[state],
* filter:(valuePath)=>valuePath.startsWith('user')
* })
*
* @param listener
* @param options
* @returns
*/
export function watch(listener:(params:any)=>void,options?:WatchOptions):()=>void{
const opts=Object.assign({
immediate:true,
depends:()=>[]
},options)

export function watch(listener:()=>void,depends: () => any[] ,options?:WatchOptions):()=>void{
const {unwatch} = heluxWatch(()=>{
listener()
},{
immediate:options?.immediate,
deps:depends
})
// @ts-ignore
const {unwatch} = heluxWatch(({triggerReasons})=>{
const valuePaths:string[][] = triggerReasons.map((reason:any)=>reason.keyPath)
listener(triggerReasons)
},opts.depends)
return unwatch
}
}



0 comments on commit 561f4b1

Please sign in to comment.