@@ -12,13 +12,23 @@ export function bind(node) {
12
12
} ;
13
13
}
14
14
15
- export function History ( { onHistoryChange } ) {
16
- // Capture browser "history go back" action and tell the server about it
17
- // Note: Browsers do not allow us to detect "history go forward" actions.
15
+ /**
16
+ * History component that captures browser "history go back" actions and notifies the server.
17
+ *
18
+ * @param {Object } props - The properties object.
19
+ * @param {Function } props.onHistoryChangeCallback - Callback function to notify the server about history changes.
20
+ * @returns {null } This component does not render any visible output.
21
+ * @description
22
+ * This component uses the `popstate` event to detect when the user navigates back in the browser history.
23
+ * It then calls the `onHistoryChangeCallback` with the current pathname and search parameters.
24
+ * Note: Browsers do not allow detection of "history go forward" actions.
25
+ * @see https://github.com/reactive-python/reactpy/pull/1224
26
+ */
27
+ export function History ( { onHistoryChangeCallback } ) {
18
28
React . useEffect ( ( ) => {
19
29
// Register a listener for the "popstate" event and send data back to the server using the `onHistoryChange` callback.
20
30
const listener = ( ) => {
21
- onHistoryChange ( {
31
+ onHistoryChangeCallback ( {
22
32
pathname : window . location . pathname ,
23
33
search : window . location . search ,
24
34
} ) ;
@@ -32,31 +42,42 @@ export function History({ onHistoryChange }) {
32
42
} ) ;
33
43
34
44
// Tell the server about the URL during the initial page load
35
- // FIXME: This currently runs every time any component is mounted due to a ReactPy core rendering bug.
45
+ // FIXME: This code is commented out since it currently runs every time any component
46
+ // is mounted due to a ReactPy core rendering bug. `FirstLoad` component is used instead.
36
47
// https://github.com/reactive-python/reactpy/pull/1224
37
- React . useEffect ( ( ) => {
38
- onHistoryChange ( {
39
- pathname : window . location . pathname ,
40
- search : window . location . search ,
41
- } ) ;
42
- return ( ) => { } ;
43
- } , [ ] ) ;
48
+
49
+ // React.useEffect(() => {
50
+ // onHistoryChange({
51
+ // pathname: window.location.pathname,
52
+ // search: window.location.search,
53
+ // });
54
+ // return () => {};
55
+ // }, []);
44
56
return null ;
45
57
}
46
58
47
- // FIXME: The Link component is unused due to a ReactPy core rendering bug
48
- // which causes duplicate rendering (and thus duplicate event listeners).
49
- // https://github.com/reactive-python/reactpy/pull/1224
50
- export function Link ( { onClick, linkClass } ) {
59
+ /**
60
+ * Link component that captures clicks on anchor links and notifies the server.
61
+ *
62
+ * @param {Object } props - The properties object.
63
+ * @param {Function } props.onClickCallback - Callback function to notify the server about link clicks.
64
+ * @param {string } props.linkClass - The class name of the anchor link.
65
+ * @returns {null } This component does not render any visible output.
66
+ */
67
+ export function Link ( { onClickCallback, linkClass } ) {
68
+ // FIXME: This component is currently unused due to a ReactPy core rendering bug
69
+ // which causes duplicate rendering (and thus duplicate event listeners).
70
+ // https://github.com/reactive-python/reactpy/pull/1224
71
+
51
72
// This component is not the actual anchor link.
52
73
// It is an event listener for the link component created by ReactPy.
53
74
React . useEffect ( ( ) => {
54
75
// Event function that will tell the server about clicks
55
76
const handleClick = ( event ) => {
56
77
event . preventDefault ( ) ;
57
78
let to = event . target . getAttribute ( "href" ) ;
58
- window . history . pushState ( { } , to , new URL ( to , window . location ) ) ;
59
- onClick ( {
79
+ window . history . pushState ( null , "" , new URL ( to , window . location ) ) ;
80
+ onClickCallback ( {
60
81
pathname : window . location . pathname ,
61
82
search : window . location . search ,
62
83
} ) ;
@@ -78,3 +99,52 @@ export function Link({ onClick, linkClass }) {
78
99
} ) ;
79
100
return null ;
80
101
}
102
+
103
+ /**
104
+ * Client-side portion of the navigate component, that allows the server to command the client to change URLs.
105
+ *
106
+ * @param {Object } props - The properties object.
107
+ * @param {Function } props.onNavigateCallback - Callback function that transmits data to the server.
108
+ * @param {string } props.to - The target URL to navigate to.
109
+ * @param {boolean } props.replace - If true, replaces the current history entry instead of adding a new one.
110
+ * @returns {null } This component does not render anything.
111
+ */
112
+ export function Navigate ( { onNavigateCallback, to, replace } ) {
113
+ React . useEffect ( ( ) => {
114
+ if ( replace ) {
115
+ window . history . replaceState ( null , "" , new URL ( to , window . location ) ) ;
116
+ } else {
117
+ window . history . pushState ( null , "" , new URL ( to , window . location ) ) ;
118
+ }
119
+ onNavigateCallback ( {
120
+ pathname : window . location . pathname ,
121
+ search : window . location . search ,
122
+ } ) ;
123
+ return ( ) => { } ;
124
+ } , [ ] ) ;
125
+
126
+ return null ;
127
+ }
128
+
129
+ /**
130
+ * FirstLoad component that captures the URL during the initial page load and notifies the server.
131
+ *
132
+ * @param {Object } props - The properties object.
133
+ * @param {Function } props.onFirstLoadCallback - Callback function to notify the server about the first load.
134
+ * @returns {null } This component does not render any visible output.
135
+ * @description
136
+ * This component sends the current URL to the server during the initial page load.
137
+ * @see https://github.com/reactive-python/reactpy/pull/1224
138
+ */
139
+ export function FirstLoad ( { onFirstLoadCallback } ) {
140
+ // FIXME: This component only exists because of a ReactPy core rendering bug, and should be removed when the bug
141
+ // is fixed. Ideally all this logic would be handled by the `History` component.
142
+ React . useEffect ( ( ) => {
143
+ onFirstLoadCallback ( {
144
+ pathname : window . location . pathname ,
145
+ search : window . location . search ,
146
+ } ) ;
147
+ return ( ) => { } ;
148
+ } , [ ] ) ;
149
+ return null ;
150
+ }
0 commit comments