Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/TS36' into TS36
Browse files Browse the repository at this point in the history
  • Loading branch information
olmobrutall committed Nov 8, 2019
2 parents ae0f000 + a6a09f2 commit 02e9a95
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Signum.React/Scripts/Frames/ContainerToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function ContainerToggleComponent(p: { children: React.ReactNode
}

return (
<div className={classes(fluid ? "container-fluid" : "container", "mt-3", "d-flex")}>
<div className={classes(fluid ? "container-fluid" : "container", "mt-3", "sf-page-container")}>
<a className="expand-window d-none d-md-block" onClick={handleExpandToggle} href="#" >
<FontAwesomeIcon icon={fluid ? "compress" : "expand"} />
</a>
Expand Down
2 changes: 1 addition & 1 deletion Signum.React/Scripts/Frames/FramePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export default function FramePage(p: FramePageProps) {
const embeddedWidgets = renderEmbeddedWidgets(wc);

return (
<div className="normal-control flex-grow-1">
<div className="normal-control">
{renderTitle()}
{renderWidgets(wc)}
{entityComponent.current && <ButtonBar ref={buttonBar} frame={frame} pack={state.pack} />}
Expand Down
9 changes: 9 additions & 0 deletions Signum.React/Scripts/Frames/Frames.css
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,12 @@ a.expand-window:hover {
.card.card-xs .card-body {
padding: 0.3em 0.5em;
}


.sf-page-container {
display: flex;
}

.sf-page-container > div{
flex-grow: 1;
}
36 changes: 22 additions & 14 deletions Signum.React/Scripts/Hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,32 +209,40 @@ export function useMounted() {
return mounted;
}

export function useThrottle<T>(value: T, limit: number): T {
export function useThrottle<T>(value: T, limit: number, options?: { enabled?: boolean }): T {
const [throttledValue, setThrottledValue] = React.useState(value);

const mounted = React.useRef(true);
const lastRequested = React.useRef<(undefined | { value: T })>(undefined);
const handleRef = React.useRef<number | undefined>(undefined);

function stop(){
if (handleRef.current)
clearTimeout(handleRef.current);

lastRequested.current = undefined;
}

React.useEffect(
() => {
if (lastRequested.current) {
lastRequested.current.value = value;
if (options && options.enabled == false) {
stop();
} else {
lastRequested.current = { value };
const handler = setTimeout(function () {
if (mounted.current) {
if (lastRequested.current) {
lastRequested.current.value = value;
} else {
lastRequested.current = { value };
handleRef.current = setTimeout(function () {
setThrottledValue(lastRequested.current!.value);
lastRequested.current = undefined;

clearTimeout(handler);
}
}, limit);
stop();
}, limit);
}
}
},
[value, limit]
[value, options && options.enabled]
);

React.useEffect(() => {
return () => { mounted.current = false; }
return () => stop();
}, []);

return throttledValue;
Expand Down
4 changes: 2 additions & 2 deletions Signum.React/Scripts/SearchControl/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function SearchPage(p: SearchPageProps) {

if (!Finder.isFindable(fo.queryName, true))
return (
<div id="divSearchPage" className="flex-grow-1">
<div id="divSearchPage">
<h3>
<span className="display-6 sf-query-title">{getQueryNiceName(fo.queryName)}</span>
<small>Error: Query not allowed {Finder.isFindable(fo.queryName, false) ? "in full screen" : ""}</small>
Expand All @@ -66,7 +66,7 @@ function SearchPage(p: SearchPageProps) {

var qs = Finder.getSettings(fo.queryName);
return (
<div id="divSearchPage" className="flex-grow-1">
<div id="divSearchPage">
<h3 className="display-6 sf-query-title">
<span>{getQueryNiceName(fo.queryName)}</span>
&nbsp;
Expand Down

3 comments on commit 02e9a95

@olmobrutall
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript 3.6, React 16.11.0 and back to react-bootstrap

This commit is a fast-forward merge of the feature-branch TS36 (now deleted). This branch started more than 2 months ago but got bigger than expected:

Updating to Typescript 3.5

It started updating to TS 3.6 when was released

Updating to React 16.11.0 (hooks all the way down)

Once updating package.json, I also updated to React 16.9.0 that contained loots of deprecations (1, 2, 3).

There was two possibilities, writing UNSAFE_ everywhere maybe using the complex getDerivedStateFromProps and getSnapshotBeforeUpdate, or just move ahead and change all the components to functional components using hooks.

We already move to hooks some months ago for the simple components, but this time almost every component has been migrated (except for SearchControlLoaded and very few others). The main benefit of hooks it that, since creating state (useState), running side-effects (useEffect), creating instance variables (useRef), etc... are all just function calls, we can extract reusable component behaviour into custom hooks that removes a lot of boilerplate in the components. Check this video to learn more.

Another important benefit of moving to hooks is that the hierarchy of line components (LineBase, EntityBase, EntityLine, EntityCombo, EntityListBase, EntityStrip, EntityRepeater, EntityTable, ...) was using inheritance or React components, but this was conflicting with React.d.ts once it introduced ReadOnly<T> in state. By moving to hooks we can create a parallel hierarchy of XXXController classes and useController hoook to reuse functionality, removing the incompatibility with the official React.d.ts.

This means we can finally remove Signum.React/node_modules from the git repository and use Signum.React/package.json to control the dependencies from the framework. It also means now there are two projects with package.json in Task Solution Explorer and you may need to yarn install the dependencies of Signum.React when you update framework.

image

image

Depending again on react-bootstrap

Signum Framework is not the only library that is having deprecation warnings after 16.9.react-widgets and react-bootstrap are also having the same problem. Fortunately they are working on it.

react-widgets has a v5 branch where they are also rewriting everything with hooks, but doesn't look ready yet.

and react-bootstrap finally has a version (1.00-beta) that works with bootstrap 4 css, rewritten using hooks and contains Typescript definitions. So I moved forward and removed most of the components in Signum.React/Scripts/Components and took again a dependency to react-bootstrap instead.

This means whenever you want to use some custom UI components (Tabs, Tooltip, Popover, etc...) you can use React Bootstrap website as reference again.

How to update

Southwind has already been updated, so you can check the diff /~https://github.com/signumsoftware/southwind/compare/d0379fb16672e5b71ddb09941e207df335542eeb..6c1d949f2d764f98f9354042cc819a8a8c9d6f9d

The main steps are:

  • Update Framework and Extensions to the latest versions. Maybe you have some problems with Signum.React/node_modules and have to remove it manually and then do yarn install there.
  • Update your YourApp.React.csproj to TypeScriptToolsVersion 3.6.
  • Update package.json to the version that southwind uses.
  • Depending how old is your application, you may need to go back to the splitted webpack.config structure, with changes in webpack.config.js, webpack.config.dll.js, vendor.js and Index.cshtml.
  • Fix the compile-time errors that you find, mainly replacing imports like
    import { UncontrolledTabs, Tab } from '@framework/Components/Tabs';
    by something like
    import { Tabs, Tab } from 'react-bootstrap';.
  • Layout.tsx probably requires big changes using react-bootstrap Nav, Navbar, ... just check how Southwind does it.
    ** Finally I strongly recommend to move all your custom components to functional components using Hooks. Many present and future tooks (custom hooks, snippets, migration regex) will assume your components are functional components, so I've built a tool that helps with the conversion to make the migration easier:

ReactHookConverter

  1. In the Load application, select G (GeneratE) -> Hook, this will show a menu with all the tsx files in YourApp.React (you can override GetFolder to run it somewhere else).
  2. Select a range of components (for example 0-10), the tool will try to convert the class components to functional components:
    *) Replace the header (export class Bla extends React.Component<BlaProps>) to a function (export function Bla(p : BlaProps))
    *) replace method / lambda field to inner function.
    *) It will replace this.props.myProp by p.myProp
    *) Replace this.state.myState by just myState
    *) Move render to the button.
    Note: The tool only works if the component is properly formatted.
  3. Manually fix each file, if necessary, by declaring useState, useRef, useEffect or higher level hooks like useAPI.

What about Typescript 3.7?

With all this changes, this update of TS took longer than expected, so TS 3.7 has already been published with the awesome ?. and ?? operators.

There is a TS37 branch with the updated branch, but I won't merge till this syntax coloring issue in VS2019 is fixed.

Conclusion

I am sure that all this changes will imporove UI development with react removing problems with this, and allowing custom hooks that make components simpler to understand, even if the change hurt at the beginning.

Be brave 💪!

@MehdyKarimpour
Copy link
Contributor

@MehdyKarimpour MehdyKarimpour commented on 02e9a95 Nov 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aswesome! 🥇

@bworld666
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice and structured summary! Thank you very much!

Please sign in to comment.