ueca-react 1.0.7 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ueca-react might be problematic. Click here for more details.
- package/LICENSE +1 -1
- package/README.md +109 -119
- package/dist/index.d.ts +266 -4
- package/dist/ueca-react.js +1453 -0
- package/docs/Arrays and Reactivity in UECA-React.md +158 -0
- package/docs/Automatic onChange Events in UECA-React.md +142 -0
- package/docs/Automatic onChanging Events in UECA-React.md +157 -0
- package/docs/Automatic onPropChange and onPropChanging Events in UECA-React.md +112 -0
- package/docs/Component Extension in UECA-React.md +275 -0
- package/docs/Component IDs in UECA-React.md +181 -0
- package/docs/{component-intergation-model.md → Component Integration Model in UECA-React.md } +4 -3
- package/docs/{component-mental-model.md → Component Mental Model in UECA-React.md } +4 -3
- package/docs/Introduction to UECA-React Components.md +190 -0
- package/docs/Introduction to UECA-React.md +24 -0
- package/docs/Lifecycle Hooks in UECA-React.md +237 -0
- package/docs/Message Bus in UECA-React.md +260 -0
- package/docs/Model Caching in UECA-React.md +144 -0
- package/docs/Property Bindings in UECA-React.md +191 -0
- package/docs/State Management in UECA-React.md +128 -0
- package/docs/Technology of UECA-React.md +45 -0
- package/docs/Tracing in UECA-React.md +110 -0
- package/docs/code-template.md +53 -27
- package/docs/index.md +31 -11
- package/package.json +68 -72
- package/dist/componentModel.d.ts +0 -127
- package/dist/componentModel.js +0 -772
- package/dist/dynamicContent.d.ts +0 -22
- package/dist/dynamicContent.js +0 -80
- package/dist/index.js +0 -29
- package/dist/messageBus.d.ts +0 -46
- package/dist/messageBus.js +0 -141
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -52
- package/docs/base-concepts.md +0 -192
- package/docs/bindings-overview.md +0 -164
- package/docs/general-code-structure.md +0 -177
- package/docs/introduction.md +0 -56
- package/docs/message-bus.md +0 -177
- package/docs/technology.md +0 -45
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Property Bindings in UECA-React
|
|
2
|
+
#bindings #props #state #reactivity
|
|
3
|
+
|
|
4
|
+
## Description
|
|
5
|
+
Property bindings in UECA-React are crucial for managing state and component interactions. They are passed to the component model hook via parameters, establishing efficient data flow and synchronization, ensuring seamless propagation of state changes across components. UECA-React supports three primary types of bindings:
|
|
6
|
+
|
|
7
|
+
- **Unidirectional Binding**: Synchronizes target property with the source value, ideal for one-way data flow.
|
|
8
|
+
- **Bidirectional Binding**: Synchronizes state between two properties, allowing updates in both directions.
|
|
9
|
+
- **Custom Binding**: Offers flexibility to transform values during binding, accommodating complex use cases.
|
|
10
|
+
|
|
11
|
+
These bindings are:
|
|
12
|
+
- **Reactive**: Automatically update dependent components when bound properties change.
|
|
13
|
+
- **Type-Safe**: Built with TypeScript for reliable and error-free data binding.
|
|
14
|
+
- **Flexible**: Support a wide range of scenarios, from simple displays to advanced state transformations.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## API/Methods
|
|
19
|
+
|
|
20
|
+
### Custom Binding
|
|
21
|
+
- **UECA.bind(getter, setter)**
|
|
22
|
+
Returns a binding object with user-defined getter and setter functions for transforming values.
|
|
23
|
+
- **Parameters**:
|
|
24
|
+
- `getter`: A function without parameters that returns the source value for target component's property synchronization.
|
|
25
|
+
- `setter`: A function with one parameter (new value) that updates the source value.
|
|
26
|
+
- **Returns**: A binding object for use in a target component's property synchronization.
|
|
27
|
+
|
|
28
|
+
### Bidirectional Binding
|
|
29
|
+
- **UECA.bind(sourceObject, propName)**
|
|
30
|
+
A simplified version of Custom Binding. Creates a bidirectional binding that synchronizes state between two properties, allowing changes to propagate in both directions.
|
|
31
|
+
- **Parameters**:
|
|
32
|
+
- `sourceObject`: The object containing the source property.
|
|
33
|
+
- `propName`: The name of the source object property to bind.
|
|
34
|
+
- **Returns**: A binding object for use in a target component's property synchronization.
|
|
35
|
+
|
|
36
|
+
### Unidirectional Binding
|
|
37
|
+
- **Arrow function returning value**
|
|
38
|
+
A shorthand for Custom Binding with a defined getter but an undefined setter. A function without parameters that returns the source value for target component's property synchronization.
|
|
39
|
+
- **Returns**: A value for use in target component's property synchronization.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Code Examples
|
|
44
|
+
|
|
45
|
+
### Unidirectional and Bidirectional Bindings
|
|
46
|
+
|
|
47
|
+
This example demonstrates input components that both read and update the form's userName property. Additionally, the form can be configured to operate in read-only mode.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Parent component (Edit Form)
|
|
51
|
+
type EditFormStruct = UECA.ComponentStruct<{
|
|
52
|
+
props: {
|
|
53
|
+
readOnly: boolean,
|
|
54
|
+
userName: {
|
|
55
|
+
firstName?: string;
|
|
56
|
+
lastName?: string
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
children: {
|
|
60
|
+
firstNameInput: InputModel,
|
|
61
|
+
lastNameInput: InputModel
|
|
62
|
+
};
|
|
63
|
+
}>;
|
|
64
|
+
|
|
65
|
+
type EditFormParams = UECA.ComponentParams<EditFormStruct>;
|
|
66
|
+
type EditFormModel = UECA.ComponentModel<EditFormStruct>;
|
|
67
|
+
|
|
68
|
+
function useEditForm(params?: EditFormParams): EditFormModel {
|
|
69
|
+
const struct: EditFormStruct = {
|
|
70
|
+
props: {
|
|
71
|
+
readOnly: false,
|
|
72
|
+
userName: {}
|
|
73
|
+
},
|
|
74
|
+
children: {
|
|
75
|
+
firstNameInput: useInput({
|
|
76
|
+
readOnly: () => model.readOnly, // Unidirectional binding
|
|
77
|
+
value: UECA.bind(() => model.userName, "firstName"), // Bidirectional binding
|
|
78
|
+
}),
|
|
79
|
+
|
|
80
|
+
lastNameInput: useInput({
|
|
81
|
+
readOnly: () => model.readOnly, // Unidirectional binding
|
|
82
|
+
value: UECA.bind(() => model.userName, "lastName"), // Bidirectional binding
|
|
83
|
+
})
|
|
84
|
+
},
|
|
85
|
+
View: () =>
|
|
86
|
+
<div id={model.htmlId()}>
|
|
87
|
+
<model.firstNameInput.View />
|
|
88
|
+
<model.lastNameInput.View />
|
|
89
|
+
</div>
|
|
90
|
+
};
|
|
91
|
+
const model = UECA.useComponent(struct, params);
|
|
92
|
+
return model;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Child Component (Input)
|
|
96
|
+
type InputStruct = UECA.ComponentStruct<{
|
|
97
|
+
props: {
|
|
98
|
+
readOnly: boolean
|
|
99
|
+
value: string
|
|
100
|
+
};
|
|
101
|
+
}>;
|
|
102
|
+
|
|
103
|
+
type InputParams = UECA.ComponentParams<InputStruct>;
|
|
104
|
+
type InputModel = UECA.ComponentModel<InputStruct>;
|
|
105
|
+
|
|
106
|
+
function useInput(params?: InputParams): InputModel {
|
|
107
|
+
const struct: InputStruct = {
|
|
108
|
+
props: {
|
|
109
|
+
readOnly: false,
|
|
110
|
+
value: ""
|
|
111
|
+
},
|
|
112
|
+
View: () =>
|
|
113
|
+
<div id={model.htmlId()}>
|
|
114
|
+
<input
|
|
115
|
+
type="text"
|
|
116
|
+
readOnly={model.readOnly}
|
|
117
|
+
value={model.value}
|
|
118
|
+
onChange={(e) => model.value = e.target.value}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
};
|
|
122
|
+
const model = UECA.useComponent(struct, params);
|
|
123
|
+
return model;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- **Explanation**:
|
|
128
|
+
The parent binds `userName.firstName` and `userName.lastName` to the children's `value` property. Changes in the inputs update the form’s state, keeping everything in sync. The form's `readOnly` property unidirectionally propagates to the `readOnly` properties of the inputs.
|
|
129
|
+
|
|
130
|
+
### Custom Binding
|
|
131
|
+
This example formats a phone number for display while storing it as digits only.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
type ContactFormStruct = UECA.ComponentStruct<{
|
|
135
|
+
props: {
|
|
136
|
+
phoneNumber: string
|
|
137
|
+
};
|
|
138
|
+
children: {
|
|
139
|
+
phoneInput: InputModel
|
|
140
|
+
};
|
|
141
|
+
}>;
|
|
142
|
+
|
|
143
|
+
type ContactFormParams = UECA.ComponentParams<ContactFormStruct>;
|
|
144
|
+
type ContactFormModel = UECA.ComponentModel<ContactFormStruct>;
|
|
145
|
+
|
|
146
|
+
function useContactForm(params?: ContactFormParams): ContactFormModel {
|
|
147
|
+
const struct: ContactFormStruct = {
|
|
148
|
+
props: {
|
|
149
|
+
phoneNumber: ""
|
|
150
|
+
},
|
|
151
|
+
children: {
|
|
152
|
+
phoneInput: useInput({
|
|
153
|
+
value: UECA.bind(
|
|
154
|
+
() => _formatPhoneNumber(model.phoneNumber), // Getter: format for display
|
|
155
|
+
(value) => (model.phoneNumber = value.replace(/\D/g, '')) // Setter: store only digits
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
},
|
|
159
|
+
View: () =>
|
|
160
|
+
<div id={model.htmlId()}>
|
|
161
|
+
<model.phoneInput.View />
|
|
162
|
+
</div>
|
|
163
|
+
};
|
|
164
|
+
const model = UECA.useComponent(struct, params);
|
|
165
|
+
return model;
|
|
166
|
+
|
|
167
|
+
// Private methods
|
|
168
|
+
function _formatPhoneNumber(phoneNumber: string): string {
|
|
169
|
+
const cleaned = ('' + phoneNumber).replace(/\D/g, '');
|
|
170
|
+
const match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
|
|
171
|
+
return match ? `(${match[1]}) ${match[2]}-${match[3]}` : phoneNumber;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
- **Explanation**:
|
|
176
|
+
The getter formats the phone number for display (e.g., `(123) 456-7890`), while the setter stores it as digits (e.g., `1234567890`), ensuring a clean model state.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Best Practices
|
|
181
|
+
- **Unidirectional Binding**: Use for read-only data display to maintain simplicity and predictability.
|
|
182
|
+
- **Bidirectional Binding**: Apply to interactive elements like forms where child components need to update the parent.
|
|
183
|
+
- **Custom Binding**: Leverage for formatting or transforming data between the model and UI, keeping logic clear and concise.
|
|
184
|
+
- **Minimize Complexity**: Keep binding logic straightforward to optimize performance and maintainability.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Notes
|
|
189
|
+
- Bindings are fully reactive, ensuring real-time updates across components.
|
|
190
|
+
- They support all data types, including primitives, objects, and arrays.
|
|
191
|
+
- For interactions beyond parent-child relationships, explore the UECA Message Bus.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# State Management in UECA-React
|
|
2
|
+
#state #management #basics #api #example #best_practices
|
|
3
|
+
|
|
4
|
+
## Description
|
|
5
|
+
State management is a core aspect of building dynamic applications in UECA-React. Unlike traditional React, which relies heavily on `useState` and `useReducer` for local state management, UECA-React introduces a model-based approach that simplifies state handling and integrates seamlessly with its lifecycle hooks. This article explores how state is managed in UECA-React, provides practical examples, and compares it to traditional React state management techniques.
|
|
6
|
+
|
|
7
|
+
### Key Concepts
|
|
8
|
+
- **Model-Based State**: State is stored in a component's model, making it accessible across lifecycle hooks and methods.
|
|
9
|
+
- **Reactive Updates**: Changes to the model automatically trigger UI updates, similar to React's state system.
|
|
10
|
+
- **Simplified API**: No need for multiple hooks or complex reducers for basic state management.
|
|
11
|
+
- **Model Cache**: Enhanced support for state persistence and caching.
|
|
12
|
+
|
|
13
|
+
## How State Works in UECA-React
|
|
14
|
+
|
|
15
|
+
In UECA-React, state is managed through the component's `model`, which is created using the `useComponent` hook. The model contains:
|
|
16
|
+
- **Props**: Initial properties passed to the component.
|
|
17
|
+
- **State**: Any mutable data defined in the model, such as counters, flags, or computed values.
|
|
18
|
+
- **Methods**: Functions that can modify the state.
|
|
19
|
+
|
|
20
|
+
The model is reactive—any changes to its properties trigger a re-render of the `View` component, ensuring the UI stays in sync with the state.
|
|
21
|
+
|
|
22
|
+
### Defining State
|
|
23
|
+
State is typically defined in the `props` section of the component structure or initialized in the `constr` or `init` lifecycle hooks. For example:
|
|
24
|
+
- Define initial state in `props`: `{ count: 0 }`.
|
|
25
|
+
- Update state in methods: `model.count++`.
|
|
26
|
+
|
|
27
|
+
### Updating State
|
|
28
|
+
State updates are performed directly on the `model` object. UECA-React detects these changes and re-renders the component automatically. No additional hooks like `setState` are required.
|
|
29
|
+
|
|
30
|
+
## Comparison to Traditional React
|
|
31
|
+
|
|
32
|
+
In traditional React, state management often involves:
|
|
33
|
+
- **useState**: For simple state updates.
|
|
34
|
+
- **useReducer**: For complex state logic.
|
|
35
|
+
- **Context**: For global state sharing.
|
|
36
|
+
|
|
37
|
+
For example, a counter in React might look like this:
|
|
38
|
+
```typescript
|
|
39
|
+
const [count, setCount] = useState(0);
|
|
40
|
+
const increment = () => setCount(count + 1);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In UECA-React, the same logic is simpler:
|
|
44
|
+
```typescript
|
|
45
|
+
props: { count: 0 },
|
|
46
|
+
methods: { increment: () => model.count++ },
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Key differences:
|
|
50
|
+
- **No Explicit Setter**: UECA-React modifies state directly on the model.
|
|
51
|
+
- **Fewer Hooks**: No need for `useState` or `useReducer` for basic state.
|
|
52
|
+
- **Tighter Integration**: State is tied to the model and lifecycle hooks, reducing boilerplate.
|
|
53
|
+
|
|
54
|
+
## Code Example
|
|
55
|
+
|
|
56
|
+
Below is an example of a toggle button component that manages a boolean state in UECA-React.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import * as UECA from "ueca-react";
|
|
60
|
+
|
|
61
|
+
// Declare the component structure
|
|
62
|
+
type ToggleStruct = UECA.ComponentStruct<{
|
|
63
|
+
props: {
|
|
64
|
+
isOn: boolean
|
|
65
|
+
};
|
|
66
|
+
methods: {
|
|
67
|
+
toggle: () => void
|
|
68
|
+
};
|
|
69
|
+
}>;
|
|
70
|
+
|
|
71
|
+
// Declare the parameters type
|
|
72
|
+
type ToggleParams = UECA.ComponentParams<ToggleStruct>;
|
|
73
|
+
|
|
74
|
+
// Declare the model type
|
|
75
|
+
type ToggleModel = UECA.ComponentModel<ToggleStruct>;
|
|
76
|
+
|
|
77
|
+
// Custom hook
|
|
78
|
+
function useToggle(params?: ToggleParams): ToggleModel {
|
|
79
|
+
const struct: ToggleStruct = {
|
|
80
|
+
props: {
|
|
81
|
+
id: useToggle.name,
|
|
82
|
+
isOn: false
|
|
83
|
+
},
|
|
84
|
+
constr: () => console.log("constr: Toggle model created"),
|
|
85
|
+
init: () => {
|
|
86
|
+
console.log("init: Toggle model initialized");
|
|
87
|
+
model.isOn = false; // Reset state on initialization
|
|
88
|
+
},
|
|
89
|
+
mount: () => console.log("mount: Toggle mounted to DOM"),
|
|
90
|
+
unmount: () => console.log("unmount: Toggle removed from DOM"),
|
|
91
|
+
methods: {
|
|
92
|
+
toggle: () => (model.isOn = !model.isOn),
|
|
93
|
+
},
|
|
94
|
+
View: () => (
|
|
95
|
+
<div id={model.htmlId()}>
|
|
96
|
+
<p>Toggle is {model.isOn ? "ON" : "OFF"}</p>
|
|
97
|
+
<button onClick={model.toggle}>Toggle</button>
|
|
98
|
+
</div>
|
|
99
|
+
),
|
|
100
|
+
};
|
|
101
|
+
const model = UECA.useComponent(struct, params);
|
|
102
|
+
return model;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Functional component
|
|
106
|
+
const Toggle = UECA.getFC(useToggle);
|
|
107
|
+
|
|
108
|
+
// Export for use in parent components
|
|
109
|
+
export { ToggleModel, useToggle, Toggle };
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
In this example:
|
|
113
|
+
- The `isOn` state is initialized as `false` in `props`.
|
|
114
|
+
- The `toggle` method flips the `isOn` value, triggering a re-render.
|
|
115
|
+
- Lifecycle hooks log events for demonstration purposes.
|
|
116
|
+
|
|
117
|
+
## Best Practices
|
|
118
|
+
- **Initialize State in `props`**: Define default state values in the `props` section to make them reactive.
|
|
119
|
+
- **Reset State in `init`**: Use the `init` hook to reset state when the component is reactivated from cache.
|
|
120
|
+
- **Keep Methods Simple**: State updates in methods should be straightforward to maintain predictability.
|
|
121
|
+
- **Avoid Overcomplicating the Model**: For complex state logic, consider breaking it into smaller components or using external stores.
|
|
122
|
+
- **Leverage Lifecycle Hooks**: Use hooks like `mount` or `draw` to perform state-dependent actions (e.g., fetching data when mounted).
|
|
123
|
+
|
|
124
|
+
## Notes
|
|
125
|
+
- State in UECA-React is local to the component’s model by default. For global state, consider integrating with root level component (e.g. App) via message bus.
|
|
126
|
+
- The reactive system ensures that only changed properties trigger re-renders, optimizing performance.
|
|
127
|
+
- State can persist across component mounts when cached, thanks to the `init` and `deinit` hooks.
|
|
128
|
+
- Unlike React, there’s no need to memoize state updates, as the model handles reactivity internally.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Technology of UECA-React
|
|
2
|
+
|
|
3
|
+
Unified Encapsulated Component Architecture (UECA) for React development leverages a blend of modern web technologies to create scalable, maintainable, and modular applications. Below is a summary of the key technologies and coding practices employed in UECA-React development:
|
|
4
|
+
|
|
5
|
+
## TypeScript
|
|
6
|
+
|
|
7
|
+
- **Core Language**: TypeScript is the primary language used for UECA-React development. It provides static typing, which enhances code quality and maintainability.
|
|
8
|
+
- **General Usage**: Most of the UECA-React code is written in general TypeScript, focusing on type safety and modern JavaScript features.
|
|
9
|
+
|
|
10
|
+
## JSX
|
|
11
|
+
|
|
12
|
+
- **User Interface**: JSX is used to describe the UI in a syntax familiar to both JavaScript and HTML, making it easier to build and understand component structures.
|
|
13
|
+
- **Integration with TypeScript**: Combined with TypeScript, JSX allows for type-checked components, reducing runtime errors and improving development efficiency.
|
|
14
|
+
|
|
15
|
+
## React
|
|
16
|
+
|
|
17
|
+
- **Minimal Usage**: The only React feature utilized in UECA-React is custom hooks for component model instantiation. This minimizes the reliance on React-specific code and simplifies the learning curve for developers new to React.
|
|
18
|
+
- **Custom Hooks**: Custom hooks are used to instantiate and manage the lifecycle of component models, integrating React’s state and effect management seamlessly into UECA.
|
|
19
|
+
|
|
20
|
+
## Coding Techniques
|
|
21
|
+
- **Property Bindings**: Synchronizes state between components and their properties automatically, reducing the need for manual updates.
|
|
22
|
+
- **Automatic OnChange\<Property> Events**: Automatically triggers events when a property changes, allowing components to react to updates or intercept changes for validation.
|
|
23
|
+
- **Component Lifecycle Hooks**:
|
|
24
|
+
Manages creation, initialization, deinitialization, mounting, and unmounting of components, ensuring predictable behavior and proper resource management.
|
|
25
|
+
- **Interaction via Message Bus**:
|
|
26
|
+
Facilitates decoupled communication between components, promoting a modular architecture by allowing components to interact without direct dependencies.
|
|
27
|
+
|
|
28
|
+
## Coding Style
|
|
29
|
+
|
|
30
|
+
- **Declarative and Modular Approach**: The UECA-React code style emphasizes a declarative and modular approach, focusing on consistency, encapsulation, and readability to create maintainable and scalable component-based applications.
|
|
31
|
+
- **Utility Classes**: While the procedural approach is preferred, utility classes can be used where appropriate, particularly for reusable functions and routines.
|
|
32
|
+
|
|
33
|
+
## Standard Code Template
|
|
34
|
+
|
|
35
|
+
- **Consistency**: To maintain consistency across different components, developers are encouraged to use a [standard code template](/docs/code-template.md) for creating new components. This ensures that all components have a uniform structure, making the codebase easier to navigate and understand.
|
|
36
|
+
- **Structural Similarity**: Keeping the code structurally similar from component to component helps in maintaining readability and reducing the cognitive load on developers when switching between different parts of the application.
|
|
37
|
+
|
|
38
|
+
## React and TypeScript
|
|
39
|
+
|
|
40
|
+
- **Web Application Foundation**: A typical UECA-React application is a web application built using React and TypeScript. React provides the component-based architecture, while TypeScript offers strong typing and modern JavaScript features.
|
|
41
|
+
- **Ban on Other React Features**: Besides custom hooks, other React features (like class components, useState, useEffect) are banned from the application code to simplify the architecture and make the codebase more approachable for developers with a TypeScript background.
|
|
42
|
+
|
|
43
|
+
## Conclusion
|
|
44
|
+
|
|
45
|
+
UECA-React development emphasizes the use of TypeScript and JSX, with minimal reliance on React-specific features. By focusing on a declarative and modular approach and maintaining structural consistency, UECA-React aims to create maintainable and scalable web applications that are easy to understand and develop. Developers familiar with TypeScript and JSX can quickly adapt to UECA, even without extensive experience in React.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Tracing in UECA-React
|
|
2
|
+
#tracing #debug #log
|
|
3
|
+
|
|
4
|
+
Logging is a crucial part of debugging and monitoring your `ueca-react` application. The UECA framework provides a built-in logging mechanism that helps you trace component behavior, track property changes, and debug application flow. This section explains how to set up and use UECA logging effectively.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
UECA logging is designed to:
|
|
9
|
+
- Capture component lifecycle events.
|
|
10
|
+
- Log property changes and updates.
|
|
11
|
+
- Provide insights into the internal workings of your components.
|
|
12
|
+
|
|
13
|
+
By default, UECA uses the browser's `console` for output, but you can customize it to suit your needs.
|
|
14
|
+
|
|
15
|
+
## Setting Up Logging
|
|
16
|
+
|
|
17
|
+
To enable logging in `ueca-react`, you need to set the `traceLog` flag in the global settings. This can be done in your entry file (e.g., `index.tsx`):
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import * as UECA from "ueca-react";
|
|
21
|
+
|
|
22
|
+
// Enable logging
|
|
23
|
+
UECA.globalSettings.traceLog = true;
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To disable logging, set `traceLog` to `false`:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import * as UECA from "ueca-react";
|
|
30
|
+
|
|
31
|
+
// Disable logging
|
|
32
|
+
UECA.globalSettings.traceLog = false;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Log Structure
|
|
36
|
+
|
|
37
|
+
When `traceLog` is enabled, UECA outputs detailed logs to the browser's console. Each log entry captures a specific event, such as:
|
|
38
|
+
|
|
39
|
+
- **Model Creation**: When a new component model is instantiated.
|
|
40
|
+
- **Property Changes**: Updates to component properties.
|
|
41
|
+
- **Lifecycle Events**: Hooks like `constr`, `init`, `mount`, `unmount`, `deinit`, `draw`, and `erase`.
|
|
42
|
+
- **Rendering**: When a component's view is rendered.
|
|
43
|
+
|
|
44
|
+
Every log entry includes:
|
|
45
|
+
- **Event Type**: The action being logged (e.g., `create model`, `change prop`).
|
|
46
|
+
- **Model ID**: A unique identifier for the component model (e.g., `model=#123456`).
|
|
47
|
+
- **Path**: The component’s hook name or its full path in the parent-child hierarchy (e.g., `useButton` or `app.ui.mainForm.button`).
|
|
48
|
+
- **Details**: Specifics like property values or changes (e.g., `"localhost"➝"127.0.0.1"`).
|
|
49
|
+
|
|
50
|
+
### Example Log
|
|
51
|
+
|
|
52
|
+
Here’s a sample log from changing a property in an input component:
|
|
53
|
+
|
|
54
|
+
```plaintext
|
|
55
|
+
change prop model=#817544 path=app.ui.appRouter.appLayout.router.generalScreen.postgresHostInput[value] "localhost"➝"127.0.0.1"
|
|
56
|
+
render view model=#817544 path=app.ui.appRouter.appLayout.router.generalScreen.postgresHostInput
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- **Event**: Property change (`change prop`).
|
|
60
|
+
- **Model ID**: `#817544`.
|
|
61
|
+
- **Path**: `app.ui.appRouter.appLayout.router.generalScreen.postgresHostInput`.
|
|
62
|
+
- **Details**: The `value` property changed from `"localhost"` to `"127.0.0.1"`, triggering a re-render.
|
|
63
|
+
|
|
64
|
+
Another example, showing the creation and initialization of a button component:
|
|
65
|
+
|
|
66
|
+
```plaintext
|
|
67
|
+
create model=#123456 path=useButton
|
|
68
|
+
init model=#123456 path=app.ui.mainForm.button
|
|
69
|
+
change prop model=#123456 path=app.ui.mainForm.button[caption] ""➝"Click Me"
|
|
70
|
+
render view model=#123456 path=app.ui.mainForm.button
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- **Events**: Model creation, initialization, property change, and rendering.
|
|
74
|
+
- **Model ID**: `#123456`.
|
|
75
|
+
- **Path**: Transitions from `useButton` to `app.ui.mainForm.button` as the component is integrated into the application hierarchy.
|
|
76
|
+
|
|
77
|
+
## Benefits for Developers
|
|
78
|
+
|
|
79
|
+
- **Traceability**: Easily track which component and property changed using `model=#<id>` and `path`.
|
|
80
|
+
- **Debugging Ease**: Observe the sequence of lifecycle events (`constr`, `init`, `mount`, etc.) to diagnose issues.
|
|
81
|
+
- **State Clarity**: Monitor property updates to verify reactive behavior.
|
|
82
|
+
- **Testing Support**: Combine with `model.fullId()` to map logs to specific components for automated tests.
|
|
83
|
+
|
|
84
|
+
## Reading the Log
|
|
85
|
+
|
|
86
|
+
To interpret a log entry:
|
|
87
|
+
1. **Identify the Event**: Determine the action (e.g., `change prop`).
|
|
88
|
+
2. **Check the Model ID**: Use `model=#<id>` to follow a specific component across events.
|
|
89
|
+
3. **Note the Path**: Understand the component’s location in the application hierarchy.
|
|
90
|
+
4. **Review Details**: See what changed or what action was performed.
|
|
91
|
+
|
|
92
|
+
For example:
|
|
93
|
+
|
|
94
|
+
```plaintext
|
|
95
|
+
change prop model=#817544 path=app.ui.appRouter.appLayout.router.generalScreen.postgresHostInput[value] "localhost"➝"127.0.0.1"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- **Event**: Property change.
|
|
99
|
+
- **Model ID**: `#817544`.
|
|
100
|
+
- **Path**: Indicates the component is an input field on the `generalScreen`.
|
|
101
|
+
- **Details**: The `value` property was updated, likely due to user input.
|
|
102
|
+
|
|
103
|
+
## Best Practices
|
|
104
|
+
|
|
105
|
+
- **Enable During Development**: Use `traceLog: true` during development or debugging to gain insights.
|
|
106
|
+
- **Disable in Production**: Set `traceLog: false` in production to avoid console clutter and improve performance.
|
|
107
|
+
- **Filter by Model ID**: Search logs for a specific `model=#<id>` to focus on one component.
|
|
108
|
+
- **Combine with Component IDs**: Use `model.fullId()` (e.g., `app.ui.mainForm.button`) to map logs to your component hierarchy.
|
|
109
|
+
|
|
110
|
+
With UECA’s tracing system, you can gain a clear window into your application’s behavior, making development and debugging more efficient.
|
package/docs/code-template.md
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
# UECA Code Template
|
|
1
|
+
# UECA-React Code Template
|
|
2
2
|
|
|
3
3
|
### TypeScript Code
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
|
-
import * as
|
|
7
|
-
import * as UEC from "ueca-react";
|
|
6
|
+
import * as UECA from "ueca-react";
|
|
8
7
|
|
|
9
|
-
// Component structure declaration
|
|
10
|
-
type MyCompStruct =
|
|
8
|
+
// Component structure declaration. All sections (props, events, children, etc) are optional.
|
|
9
|
+
type MyCompStruct = UECA.ComponentStruct<{
|
|
11
10
|
props: {
|
|
12
11
|
// declaration of properties
|
|
13
12
|
},
|
|
@@ -25,14 +24,15 @@ type MyCompStruct = UEC.ComponentStruct<{
|
|
|
25
24
|
}
|
|
26
25
|
}>;
|
|
27
26
|
|
|
28
|
-
type MyCompParams =
|
|
29
|
-
type MyCompModel =
|
|
27
|
+
type MyCompParams = UECA.ComponentParams<MyCompStruct>; // component parameters type (props & events & hooks from MyCompStruct)
|
|
28
|
+
type MyCompModel = UECA.ComponentModel<MyCompStruct>; // component model type
|
|
30
29
|
|
|
31
30
|
// Custom react hook. Returns component model.
|
|
32
31
|
function useMyComp(params?: MyCompParams): MyCompModel {
|
|
33
32
|
const struct: MyCompStruct = {
|
|
34
33
|
props: {
|
|
35
34
|
// initialization of properties
|
|
35
|
+
id: useMyComp.name
|
|
36
36
|
},
|
|
37
37
|
|
|
38
38
|
children: {
|
|
@@ -51,31 +51,50 @@ function useMyComp(params?: MyCompParams): MyCompModel {
|
|
|
51
51
|
// initialization of listening messages
|
|
52
52
|
},
|
|
53
53
|
|
|
54
|
+
constr: () => {
|
|
55
|
+
// called once when the component model is created
|
|
56
|
+
},
|
|
57
|
+
|
|
54
58
|
init: () => {
|
|
55
|
-
//
|
|
59
|
+
// called after constr() when the model is first created or when it is retrieved from the cache
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
deinit: () => {
|
|
63
|
+
// called when the component loses its React context, making the model inactive (e.g., when it's cached but not in use)
|
|
56
64
|
},
|
|
57
65
|
|
|
58
66
|
mount: () => {
|
|
59
|
-
// called
|
|
67
|
+
// called when the component is mounted into React DOM
|
|
60
68
|
},
|
|
61
69
|
|
|
62
70
|
unmount: () => {
|
|
63
|
-
// called
|
|
71
|
+
// called when the component is removed from React DOM
|
|
64
72
|
},
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
draw: () => {
|
|
75
|
+
// called when the component's view is rendered
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
erase: () => {
|
|
79
|
+
// called when the component's UI is about to be removed
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// сomponent UI presentation
|
|
83
|
+
View: () => <></>
|
|
68
84
|
}
|
|
69
85
|
|
|
70
|
-
//
|
|
71
|
-
const model: MyCompModel =
|
|
86
|
+
// returns new component model or cached model (for subsequent calls)
|
|
87
|
+
const model: MyCompModel = UECA.useComponent(struct, params);
|
|
72
88
|
return model;
|
|
73
89
|
|
|
74
|
-
// Private methods
|
|
90
|
+
// Private methods
|
|
91
|
+
function _somePrivateMethod() {
|
|
92
|
+
|
|
93
|
+
}
|
|
75
94
|
}
|
|
76
95
|
|
|
77
96
|
// React functional component
|
|
78
|
-
const MyComp =
|
|
97
|
+
const MyComp = UECA.getFC(useMyComp);
|
|
79
98
|
|
|
80
99
|
export { MyCompModel, useMyComp, MyComp }
|
|
81
100
|
|
|
@@ -83,14 +102,13 @@ export { MyCompModel, useMyComp, MyComp }
|
|
|
83
102
|
|
|
84
103
|
### VisualCode Code Snippets
|
|
85
104
|
```json
|
|
86
|
-
"UECA Component": {
|
|
105
|
+
"UECA-React Component": {
|
|
87
106
|
"prefix": "ueca-component",
|
|
88
107
|
"body": [
|
|
89
|
-
"import * as
|
|
90
|
-
"import * as UEC from \"ueca-react\";",
|
|
108
|
+
"import * as UECA from \"ueca-react\";",
|
|
91
109
|
"",
|
|
92
|
-
"// Component structure declaration",
|
|
93
|
-
"type ${1:MyComp}Struct =
|
|
110
|
+
"// Component structure declaration. All sections (props, events, children, etc) are optional.",
|
|
111
|
+
"type ${1:MyComp}Struct = UECA.ComponentStruct<{",
|
|
94
112
|
" props: {",
|
|
95
113
|
" // declaration of properties",
|
|
96
114
|
" },",
|
|
@@ -108,14 +126,15 @@ export { MyCompModel, useMyComp, MyComp }
|
|
|
108
126
|
" }",
|
|
109
127
|
"}>;",
|
|
110
128
|
"",
|
|
111
|
-
"type ${1:MyComp}Params =
|
|
112
|
-
"type ${1:MyComp}Model =
|
|
129
|
+
"type ${1:MyComp}Params = UECA.ComponentParams<${1:MyComp}Struct>; // component parameters type (props, events and hooks from ${1:MyComp}Struct)",
|
|
130
|
+
"type ${1:MyComp}Model = UECA.ComponentModel<${1:MyComp}Struct>; // component model type",
|
|
113
131
|
"",
|
|
114
132
|
"// Custom react hook. Returns component model.",
|
|
115
133
|
"function use${1:MyComp}(params?: ${1:MyComp}Params): ${1:MyComp}Model {",
|
|
116
134
|
" const struct: ${1:MyComp}Struct = {",
|
|
117
135
|
" props: {",
|
|
118
136
|
" // initialization of properties",
|
|
137
|
+
" id: use${1:MyComp}.name",
|
|
119
138
|
" },",
|
|
120
139
|
"",
|
|
121
140
|
" children: {",
|
|
@@ -134,6 +153,10 @@ export { MyCompModel, useMyComp, MyComp }
|
|
|
134
153
|
" // initialization of listening messages",
|
|
135
154
|
" },",
|
|
136
155
|
"",
|
|
156
|
+
" constr: () => { ",
|
|
157
|
+
" // called once when the component model is created",
|
|
158
|
+
" },",
|
|
159
|
+
"",
|
|
137
160
|
" init: () => { ",
|
|
138
161
|
" // final initialization. called once for a newly created component model instance",
|
|
139
162
|
" },",
|
|
@@ -147,22 +170,25 @@ export { MyCompModel, useMyComp, MyComp }
|
|
|
147
170
|
" },",
|
|
148
171
|
"",
|
|
149
172
|
" // Component UI presentation",
|
|
150
|
-
" View: () =>
|
|
173
|
+
" View: () => <></>",
|
|
151
174
|
" }",
|
|
152
175
|
"",
|
|
153
176
|
" //instantiate component model. return previously created model for subsequent calls.",
|
|
154
|
-
" const model: ${1:MyComp}Model =
|
|
177
|
+
" const model: ${1:MyComp}Model = UECA.useComponent(struct, params);",
|
|
155
178
|
" return model;",
|
|
156
179
|
"",
|
|
157
180
|
" // Private methods ",
|
|
181
|
+
" function _somePrivateMethod() {",
|
|
182
|
+
"",
|
|
183
|
+
" }",
|
|
158
184
|
"}",
|
|
159
185
|
"",
|
|
160
186
|
"// React functional component",
|
|
161
|
-
"const ${1:MyComp}=
|
|
187
|
+
"const ${1:MyComp}= UECA.getFC(use${1:MyComp});",
|
|
162
188
|
"",
|
|
163
189
|
"export { ${1:MyComp}Model, use${1:MyComp}, ${1:MyComp} }",
|
|
164
190
|
""
|
|
165
191
|
],
|
|
166
|
-
"description": "UECA Component"
|
|
192
|
+
"description": "UECA-React Component"
|
|
167
193
|
}
|
|
168
194
|
```
|