<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://izara.io/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nink</id>
	<title>Izara Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://izara.io/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nink"/>
	<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php/Special:Contributions/Nink"/>
	<updated>2026-05-07T13:32:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_talk:Nink&amp;diff=2413</id>
		<title>User talk:Nink</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_talk:Nink&amp;diff=2413"/>
		<updated>2023-07-26T01:41:22Z</updated>

		<summary type="html">&lt;p&gt;Nink: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;h1&amp;gt;useEffect: Render Cycle and Cleanup Function&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;In the sitePageConfigOutput, there're two useEffects to be used which pulls two different response data from the backend.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  useEffect(() =&amp;gt; {&lt;br /&gt;
    // let cancel = false;&lt;br /&gt;
    async function sendRequestA(objectFormConfigId) {&lt;br /&gt;
      let responseDataA = await sendBackendRequestA(&lt;br /&gt;
        &amp;quot;post&amp;quot;,&lt;br /&gt;
        &amp;quot;https://0yzv0v3f86.execute-api.us-west-2.amazonaws.com/Test/Email/List&amp;quot;,&lt;br /&gt;
        {&lt;br /&gt;
          objectFormConfigId: objectFormConfigId,&lt;br /&gt;
        }&lt;br /&gt;
      );&lt;br /&gt;
      cancel = false;&lt;br /&gt;
      if (cancel === false) {&lt;br /&gt;
        setObjectFormConfig((objectFormConfig) =&amp;gt; {&lt;br /&gt;
          objectFormConfig.objectFormConfigId = responseDataA;&lt;br /&gt;
          return { ...objectFormConfig };&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendRequestA(getObjectFormConfig);&lt;br /&gt;
    return () =&amp;gt; {&lt;br /&gt;
      cancel = true&lt;br /&gt;
    };&lt;br /&gt;
  }, [getObjectFormConfig]);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Problems&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;useEffect returns the clean up function before the effect&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If condition renders only once instead of four times&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Possible causes&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Due to the async function, useEffect has to skip the async function and push it into the update queue, so there’ll be four sendRequestA in the queue waiting to be rendered. While waiting, useEffect will return the cleanup function.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;useEffect remembers the last value, then renders the tasks in the queue. Therefore, for index 0 to 2, cancel will be set to true (due to the cleanup) and to false for the last index (3).&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Solution&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Set cancel to false right before the if condition.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Note&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
The reason why the last index doesn’t clean up after finishing the effect is still unknown. It might happen because all the tasks are done, so there’s no need to clean up anymore. However, the cleanup function runs when a component unmounts and after each (re-)render. Therefore, the last index still needs the cleanup.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Resources&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;https://retool.com/blog/the-react-lifecycle-methods-and-hooks-explained/&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;https://dev.to/otamnitram/react-useeffect-cleanup-how-and-when-to-use-it-2hbm&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;https://hackernoon.com/cleanup-functions-in-reacts-useeffect-hook-explained&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;https://blog.bitsrc.io/everything-you-need-to-know-about-useeffects-clean-up-function-in-react-dfa6bc75f4f3&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;https://dev.to/haseeb1009/avoid-ignoring-react-hooksexhaustive-deps-linting-warnings-244f#:~:text=It%20might%20not%20seem%20like,with%20given%20ways%20instead%20disabling.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>Nink</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_talk:Nink&amp;diff=2412</id>
		<title>User talk:Nink</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_talk:Nink&amp;diff=2412"/>
		<updated>2023-07-25T07:16:12Z</updated>

		<summary type="html">&lt;p&gt;Nink: Created page with &amp;quot;&amp;lt;h1&amp;gt;useEffect: Render Cycle and Cleanup Function&amp;lt;/h1&amp;gt; &amp;lt;p&amp;gt;In the sitePageConfigOutput, there're two useEffects to be used which pulls two different response data from the backend.&amp;lt;/p&amp;gt; &amp;lt;code&amp;gt;   useEffect(() =&amp;gt; {     // let cancel = false;     async function sendRequestA(objectFormConfigId) {       let responseDataA = await sendBackendRequestA(         &amp;quot;post&amp;quot;,         &amp;quot;https://0yzv0v3f86.execute-api.us-west-2.amazonaws.com/Test/Email/List&amp;quot;,         {           objectFormCon...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;h1&amp;gt;useEffect: Render Cycle and Cleanup Function&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;In the sitePageConfigOutput, there're two useEffects to be used which pulls two different response data from the backend.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  useEffect(() =&amp;gt; {&lt;br /&gt;
    // let cancel = false;&lt;br /&gt;
    async function sendRequestA(objectFormConfigId) {&lt;br /&gt;
      let responseDataA = await sendBackendRequestA(&lt;br /&gt;
        &amp;quot;post&amp;quot;,&lt;br /&gt;
        &amp;quot;https://0yzv0v3f86.execute-api.us-west-2.amazonaws.com/Test/Email/List&amp;quot;,&lt;br /&gt;
        {&lt;br /&gt;
          objectFormConfigId: objectFormConfigId,&lt;br /&gt;
        }&lt;br /&gt;
      );&lt;br /&gt;
      cancel = false;&lt;br /&gt;
      if (cancel === false) {&lt;br /&gt;
        setObjectFormConfig((objectFormConfig) =&amp;gt; {&lt;br /&gt;
          objectFormConfig.objectFormConfigId = responseDataA;&lt;br /&gt;
          return { ...objectFormConfig };&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendRequestA(getObjectFormConfig);&lt;br /&gt;
    return () =&amp;gt; {&lt;br /&gt;
      cancel = true&lt;br /&gt;
    };&lt;br /&gt;
  }, [getObjectFormConfig]);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Problems&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;useEffect returns the clean up function before the effect&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If condition renders only once instead of four times&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Possible causes&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Due to the async function, useEffect has to skip the async function and push it into the update queue, so there’ll be four sendRequestA in the queue waiting to be rendered. While waiting, useEffect will return the cleanup function.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;useEffect remembers the last value, then renders the tasks in the queue. Therefore, for index 0 to 2, cancel will be set to true (due to the cleanup) and to false for the last index (3).&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Solution&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Set cancel to false right before the if condition.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Note&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
The reason why the last index doesn’t clean up after finishing the effect is still unknown. It might happen because all the tasks are done, so there’s no need to clean up anymore. However, the cleanup function runs when a component unmounts and after each (re-)render. Therefore, the last index still needs the cleanup.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Nink</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SitePage_Config&amp;diff=2406</id>
		<title>Service - SitePage Config</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SitePage_Config&amp;diff=2406"/>
		<updated>2023-07-07T05:21:38Z</updated>

		<summary type="html">&lt;p&gt;Nink: /* sitePageConfig Object */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Manages configuration for site pages created by users that can include elements such as tables, forms to create/update objects, graphs, etc&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
https://bitbucket.org/izara-core-shared/izara-core-shared-sitepage-config&lt;br /&gt;
&lt;br /&gt;
= DynamoDB tables =&lt;br /&gt;
&lt;br /&gt;
== SitePageConfigMain ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	sitePageConfigId: &amp;quot;xx&amp;quot;, // {random uuid}&lt;br /&gt;
	sitePageConfig: &amp;quot;xx&amp;quot;, // json encoded object of configuration&lt;br /&gt;
	sitePageConfigName: &amp;quot;yy&amp;quot;, // user specified name of the config&lt;br /&gt;
	userId: &amp;quot;xx&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* partition key: sitePageConfigId&lt;br /&gt;
* sort key: {none}&lt;br /&gt;
&lt;br /&gt;
== UsersSitePageConfigs ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	userId: &amp;quot;xx&amp;quot; // user who owns the sitePageConfig&lt;br /&gt;
	sitePageConfigId: &amp;quot;xx&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* partition key: userId&lt;br /&gt;
* sort key: sitePageConfigId&lt;br /&gt;
&lt;br /&gt;
= sitePageConfig Object = &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	pageName: &amp;quot;xx&amp;quot;, // set by the creator of the page, displayed in setup pages eg menuConfig&lt;br /&gt;
	&lt;br /&gt;
	// grouping/row/cell/elements structure same tableConfig&lt;br /&gt;
	// add css theme and overwrite settings&lt;br /&gt;
	// standardize property names to match tableConfig structure (eg elementTypes)&lt;br /&gt;
	sections: [&lt;br /&gt;
		{&lt;br /&gt;
			sectionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupings: [&lt;br /&gt;
				{&lt;br /&gt;
					groupingName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
					rows: [&lt;br /&gt;
						{&lt;br /&gt;
							rowName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
							cells: [&lt;br /&gt;
								{&lt;br /&gt;
									cellName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
									elements: [&lt;br /&gt;
										{&lt;br /&gt;
											pageElementType: &amp;quot;table&amp;quot;, //&amp;quot;table&amp;quot;|&amp;quot;formObjectCreate&amp;quot;|&amp;quot;formObjectEdit&amp;quot;|&amp;quot;freeText&amp;quot;&lt;br /&gt;
											tableConfigId: &amp;quot;tableConfigId_1&amp;quot;,&lt;br /&gt;
											//optional:&lt;br /&gt;
											overwriteFilter: &amp;quot;&amp;quot;&lt;br /&gt;
										},&lt;br /&gt;
										{&lt;br /&gt;
											pageElementType: &amp;quot;formObjectCreate&amp;quot;,&lt;br /&gt;
											objectCreateConfigId: &amp;quot;formObjectCreateConfigId_1&amp;quot;,&lt;br /&gt;
											//objectType set in formObjectCreateConfig&lt;br /&gt;
										},&lt;br /&gt;
										{&lt;br /&gt;
											pageElementType: &amp;quot;formObjectEdit&amp;quot;,&lt;br /&gt;
											objectFormConfigId: &amp;quot;formObjectEditConfigId_1&amp;quot;,&lt;br /&gt;
											//optional:&lt;br /&gt;
											identifiers: { // check structure with SeaGame&lt;br /&gt;
											  xx: &amp;quot;yy&amp;quot;,&lt;br /&gt;
											  qq: &amp;quot;rr&amp;quot;&lt;br /&gt;
											}&lt;br /&gt;
											//objectType set in formObjectEditConfig&lt;br /&gt;
										},&lt;br /&gt;
										{&lt;br /&gt;
											pageElementType: &amp;quot;freeText&amp;quot;,&lt;br /&gt;
											text: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
										},					&lt;br /&gt;
									]&lt;br /&gt;
								},&lt;br /&gt;
								// ..&lt;br /&gt;
							]&lt;br /&gt;
						},&lt;br /&gt;
						//...&lt;br /&gt;
					],&lt;br /&gt;
				},&lt;br /&gt;
				//...&lt;br /&gt;
			],&lt;br /&gt;
		},&lt;br /&gt;
		//...&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Multiple pageElements on one page =&lt;br /&gt;
&lt;br /&gt;
* any number of tables or forms can be shown on a single page, presented according to groupings/rows structure&lt;br /&gt;
* each table and form is independent from each other, so each form has it's own submission and submits independently from other forms&lt;br /&gt;
* each form receives it's identifiers independently, so each form will check if identifiers sent by menuConfig, if not will show inputs for them&lt;br /&gt;
&lt;br /&gt;
= Interaction with MenuConfig =&lt;br /&gt;
&lt;br /&gt;
* MenuElements set to sitePages link to a sitePageConfigId&lt;br /&gt;
* if sitePageConfig has any &amp;quot;objectForm&amp;quot;|&amp;quot;objectDisplay&amp;quot; pageElements then menuConfig offers to hardcode identifierIds, or eg a popup to enter the identifiers&lt;br /&gt;
* if no identifierIds are sent to &amp;quot;objectForm&amp;quot;|&amp;quot;objectDisplay&amp;quot; page then the page initially offers inputs to set the identifierIds (no pageElements shown) for that pageElement&lt;br /&gt;
&lt;br /&gt;
= Authorizers =&lt;br /&gt;
&lt;br /&gt;
* after have identifierIds we can pull the data for that object&lt;br /&gt;
* also need to pull the targetId for any authorizer which will need to be sent with submissions&lt;br /&gt;
* might be cases where we can edit appLevel objects? In which case tagetId not required&lt;br /&gt;
&lt;br /&gt;
= Create or Display/Update multiple linked objects =&lt;br /&gt;
&lt;br /&gt;
* considering having new pageTypes that hook into ImportData flow for creating multiple objects according to object relationships&lt;br /&gt;
* basic &amp;quot;createObject&amp;quot;|&amp;quot;displayObject&amp;quot; pages send directly to service that is responsible for objectType to perform the action&lt;br /&gt;
* multiple linked object submission will format request and send to ImportData which creates PendingObject/Links and processes accordingly&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SitePage Config|SitePage Config]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SitePage Config]]&lt;/div&gt;</summary>
		<author><name>Nink</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Frontend_Page_-_Configure_MenuConfig&amp;diff=2368</id>
		<title>Frontend Page - Configure MenuConfig</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Frontend_Page_-_Configure_MenuConfig&amp;diff=2368"/>
		<updated>2023-06-13T07:20:10Z</updated>

		<summary type="html">&lt;p&gt;Nink: Created page with &amp;quot;= Overview =  Frontend page for creating and editing MenuConfigs  = Repository =  = visibleObj Object =   &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt; let visibleObj = { 	visibleRowIndex: 0, // row index we have open on page 	visibleRenameRowIndex: 0, // row index currently renaming 	rows:[ 		{ 			menuElements: [ 				{ 					show: false, // whether the menuElement settings are expanded 					menuText 					menuElements: [ // if menuElement is elementType menu, will have child menuElements...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Frontend page for creating and editing MenuConfigs&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
= visibleObj Object = &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
let visibleObj = {&lt;br /&gt;
	visibleRowIndex: 0, // row index we have open on page&lt;br /&gt;
	visibleRenameRowIndex: 0, // row index currently renaming&lt;br /&gt;
	rows:[&lt;br /&gt;
		{&lt;br /&gt;
			menuElements: [&lt;br /&gt;
				{&lt;br /&gt;
					show: false, // whether the menuElement settings are expanded&lt;br /&gt;
					menuText&lt;br /&gt;
					menuElements: [ // if menuElement is elementType menu, will have child menuElements&lt;br /&gt;
					&lt;br /&gt;
					],&lt;br /&gt;
				},&lt;br /&gt;
				// ..&lt;br /&gt;
			]&lt;br /&gt;
		},&lt;br /&gt;
		// ..&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== menuElements recursion == &lt;br /&gt;
&lt;br /&gt;
* Menu elements are nested to any level&lt;br /&gt;
* Structure of rows and menuElements in visible object matches structure of menuConfig/menuConfigSetting&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[Category:Frontend pages| Configure MenuConfig]]&lt;/div&gt;</summary>
		<author><name>Nink</name></author>
	</entry>
</feed>