Update from obsidian - thinkpad
Affected files: .obsidian/community-plugins.json .obsidian/hotkeys.json .obsidian/plugins/obsidian-excalidraw-plugin/data.json .obsidian/plugins/obsidian-omnivore/data.json .obsidian/plugins/obsidian-tasks-plugin/data.json .obsidian/plugins/obsidian-tasks-plugin/main.js .obsidian/plugins/obsidian-tasks-plugin/manifest.json .obsidian/plugins/obsidian-tasks-plugin/styles.css .obsidian/plugins/update-time-on-edit/data.json 01. Projects/Página Personal/Pages/Landing Page.md 01. Projects/Página Personal/Pages/Landing Page.pdf 01. Projects/Página Personal/README.md 02. Areas/Escape Latam/Canada.md 02. Areas/Escape Latam/New Zeldand.md 03. Resources/Design/Design.md 03. Resources/Design/Layouts.md 03. Resources/Development/CSS and Component Libraries.md 04. Periodic/01. Daily/2024-02-26.md README.md Read Later/2024-02-26 - How to Learn the Hard Parts of React – and Tips to Conquer Them.md Read Later/You Don’t Actually Want Open World Games - YouTube.md templates/Intermediate Package.md templates/Project Readme.md
This commit is contained in:
parent
6f27cdc5e9
commit
bcd5cfe297
23 changed files with 140533 additions and 853 deletions
1
.obsidian/community-plugins.json
vendored
1
.obsidian/community-plugins.json
vendored
|
|
@ -15,6 +15,5 @@
|
||||||
"update-time-on-edit",
|
"update-time-on-edit",
|
||||||
"periodic-notes",
|
"periodic-notes",
|
||||||
"calendar",
|
"calendar",
|
||||||
"obsidian-tasks-plugin",
|
|
||||||
"homepage"
|
"homepage"
|
||||||
]
|
]
|
||||||
9
.obsidian/hotkeys.json
vendored
9
.obsidian/hotkeys.json
vendored
|
|
@ -49,5 +49,14 @@
|
||||||
],
|
],
|
||||||
"key": "L"
|
"key": "L"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"file-explorer:reveal-active-file": [
|
||||||
|
{
|
||||||
|
"modifiers": [
|
||||||
|
"Mod",
|
||||||
|
"Shift"
|
||||||
|
],
|
||||||
|
"key": "R"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
8384
.obsidian/plugins/obsidian-excalidraw-plugin/data.json
vendored
8384
.obsidian/plugins/obsidian-excalidraw-plugin/data.json
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
||||||
"dateSavedFormat": "yyyy-MM-dd HH:mm:ss",
|
"dateSavedFormat": "yyyy-MM-dd HH:mm:ss",
|
||||||
"apiKey": "ec3bba50-4770-471b-99b1-9953ca523d8c",
|
"apiKey": "ec3bba50-4770-471b-99b1-9953ca523d8c",
|
||||||
"filter": "ADVANCED",
|
"filter": "ADVANCED",
|
||||||
"syncAt": "2024-02-24T13:34:52",
|
"syncAt": "2024-02-29T18:19:41",
|
||||||
"customQuery": "in:archive has:highlights",
|
"customQuery": "in:archive has:highlights",
|
||||||
"template": "# {{{title}}}\n\n{{# note }}\n## Notes\n\n{{{ note }}}\n{{/ note }}\n{{#highlights.length}}\n## Highlights\n\n{{#highlights}}\n{{{text}}} \n{{#note}}\n\n> [!note]\n> {{{note}}}\n{{/note}}\n\n[source]({{{highlightUrl}}}) {{#labels}} #{{name}} {{/labels}}\n\n---\n\n{{/highlights}}\n{{/highlights.length}}\n## Original\n\n{{{ content }}}",
|
"template": "# {{{title}}}\n\n{{# note }}\n## Notes\n\n{{{ note }}}\n{{/ note }}\n{{#highlights.length}}\n## Highlights\n\n{{#highlights}}\n{{{text}}} \n{{#note}}\n\n> [!note]\n> {{{note}}}\n{{/note}}\n\n[source]({{{highlightUrl}}}) {{#labels}} #{{name}} {{/labels}}\n\n---\n\n{{/highlights}}\n{{/highlights.length}}\n## Original\n\n{{{ content }}}",
|
||||||
"highlightOrder": "LOCATION",
|
"highlightOrder": "LOCATION",
|
||||||
|
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
{
|
|
||||||
"globalQuery": "path does not include templates\ntags does not include #feat",
|
|
||||||
"globalFilter": "",
|
|
||||||
"removeGlobalFilter": false,
|
|
||||||
"taskFormat": "tasksPluginEmoji",
|
|
||||||
"setCreatedDate": true,
|
|
||||||
"setDoneDate": true,
|
|
||||||
"setCancelledDate": true,
|
|
||||||
"autoSuggestInEditor": true,
|
|
||||||
"autoSuggestMinMatch": 0,
|
|
||||||
"autoSuggestMaxItems": 6,
|
|
||||||
"provideAccessKeys": true,
|
|
||||||
"useFilenameAsScheduledDate": false,
|
|
||||||
"filenameAsDateFolders": [],
|
|
||||||
"recurrenceOnNextLine": false,
|
|
||||||
"statusSettings": {
|
|
||||||
"coreStatuses": [
|
|
||||||
{
|
|
||||||
"symbol": " ",
|
|
||||||
"name": "Todo",
|
|
||||||
"nextStatusSymbol": "x",
|
|
||||||
"availableAsCommand": true,
|
|
||||||
"type": "TODO"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"symbol": "x",
|
|
||||||
"name": "Done",
|
|
||||||
"nextStatusSymbol": " ",
|
|
||||||
"availableAsCommand": true,
|
|
||||||
"type": "DONE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"customStatuses": [
|
|
||||||
{
|
|
||||||
"symbol": "/",
|
|
||||||
"name": "In Progress",
|
|
||||||
"nextStatusSymbol": "x",
|
|
||||||
"availableAsCommand": true,
|
|
||||||
"type": "IN_PROGRESS"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"symbol": "-",
|
|
||||||
"name": "Cancelled",
|
|
||||||
"nextStatusSymbol": " ",
|
|
||||||
"availableAsCommand": true,
|
|
||||||
"type": "CANCELLED"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"features": {
|
|
||||||
"INTERNAL_TESTING_ENABLED_BY_DEFAULT": true
|
|
||||||
},
|
|
||||||
"generalSettings": {},
|
|
||||||
"headingOpened": {
|
|
||||||
"Core Statuses": true,
|
|
||||||
"Custom Statuses": true
|
|
||||||
},
|
|
||||||
"debugSettings": {
|
|
||||||
"ignoreSortInstructions": false,
|
|
||||||
"showTaskHiddenData": false
|
|
||||||
},
|
|
||||||
"loggingOptions": {
|
|
||||||
"minLevels": {
|
|
||||||
"": "info",
|
|
||||||
"tasks": "info",
|
|
||||||
"tasks.Cache": "info",
|
|
||||||
"tasks.Events": "info",
|
|
||||||
"tasks.File": "info",
|
|
||||||
"tasks.Query": "info",
|
|
||||||
"tasks.Task": "info"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
348
.obsidian/plugins/obsidian-tasks-plugin/main.js
vendored
348
.obsidian/plugins/obsidian-tasks-plugin/main.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"id": "obsidian-tasks-plugin",
|
|
||||||
"name": "Tasks",
|
|
||||||
"version": "6.0.0",
|
|
||||||
"minAppVersion": "1.1.1",
|
|
||||||
"description": "Task management for Obsidian",
|
|
||||||
"helpUrl": "https://publish.obsidian.md/tasks/",
|
|
||||||
"author": "Martin Schenck and Clare Macrae",
|
|
||||||
"authorUrl": "https://github.com/obsidian-tasks-group",
|
|
||||||
"fundingUrl": "https://github.com/sponsors/claremacrae",
|
|
||||||
"isDesktopOnly": false
|
|
||||||
}
|
|
||||||
366
.obsidian/plugins/obsidian-tasks-plugin/styles.css
vendored
366
.obsidian/plugins/obsidian-tasks-plugin/styles.css
vendored
|
|
@ -1,366 +0,0 @@
|
||||||
:root {
|
|
||||||
--tasks-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z'/></svg>");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fix indentation of wrapped task lines in Tasks search results, when in Live Preview. */
|
|
||||||
ul.contains-task-list .task-list-item-checkbox {
|
|
||||||
margin-inline-start: calc(var(--checkbox-size) * -1.5) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-tasks-query-explanation{
|
|
||||||
/* Prevent long explanation lines wrapping, so they are more readable,
|
|
||||||
especially on small screens.
|
|
||||||
|
|
||||||
A horizontal scroll bar will be displayed, if the explanation
|
|
||||||
is too wide to fit.
|
|
||||||
*/
|
|
||||||
--code-white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-count {
|
|
||||||
color: var(--text-faint);
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tooltip pop up above the description in short mode */
|
|
||||||
.tooltip.pop-up {
|
|
||||||
animation: pop-up-animation 200ms forwards ease-in-out;
|
|
||||||
}
|
|
||||||
@keyframes pop-up-animation {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-100%) scale(1);
|
|
||||||
}
|
|
||||||
20% {
|
|
||||||
opacity: 0.7;
|
|
||||||
transform: translateY(-100%) scale(1.02);
|
|
||||||
}
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(-100%) scale(1.05);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(-100%) scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Edit and postpone */
|
|
||||||
.tasks-edit, .tasks-postpone {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-left: .33em;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: var(--font-interface);
|
|
||||||
color: var(--text-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
a.tasks-edit, a.tasks-postpone {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-edit::after {
|
|
||||||
content: '📝';
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-postpone::after {
|
|
||||||
content: '⏩';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Urgency score */
|
|
||||||
.tasks-urgency {
|
|
||||||
font-size: var(--font-ui-smaller);
|
|
||||||
font-family: var(--font-interface);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: var(--radius-s);
|
|
||||||
color: var(--text-normal);
|
|
||||||
background-color: var(--background-secondary);
|
|
||||||
margin-left: 0.5em;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.internal-link.internal-link-short-mode {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-list-text {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-list-text .tooltip {
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide tags that Obsidian recognises, if `hide tags` instruction was used. */
|
|
||||||
.tasks-layout-hide-tags .task-description a.tag {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Workaround for issue #2073: Enabling the plugin causes blockIds to be not hidden in reading view
|
|
||||||
https://github.com/obsidian-tasks-group/obsidian-tasks/issues/2073 */
|
|
||||||
.task-list-item .task-block-link{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-setting-important {
|
|
||||||
color: red;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**------------------------------------------------------------------------
|
|
||||||
** MODAL
|
|
||||||
*------------------------------------------------------------------------**/
|
|
||||||
|
|
||||||
.tasks-modal-section + .tasks-modal-section {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-section label {
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-section label > span {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal .with-accesskeys .accesskey-first::first-letter,
|
|
||||||
.tasks-modal .with-accesskeys .accesskey {
|
|
||||||
text-decoration: underline;
|
|
||||||
text-underline-offset: 1pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-buttons {
|
|
||||||
position: sticky;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: var(--modal-background);
|
|
||||||
padding-bottom: 16px;
|
|
||||||
padding-top: 16px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 3fr 1fr;
|
|
||||||
column-gap: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal label + input[type="checkbox"] {
|
|
||||||
margin-left: 0.67em;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal input[type="text"] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal textarea {
|
|
||||||
width: 100%;
|
|
||||||
min-height: calc(var(--input-height) * 2);
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 4em 8em 8em 8em;
|
|
||||||
grid-column-gap: 1.33em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities span {
|
|
||||||
line-height: 1.41;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities label {
|
|
||||||
border-radius: var(--input-radius);
|
|
||||||
padding: 2px 3px;
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row-start: 1;
|
|
||||||
grid-row-end: 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities input:focus + label {
|
|
||||||
box-shadow: 0 0 0 2px var(--background-modifier-border-focus);
|
|
||||||
border-color: var(--background-modifier-border-focus);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities input:checked + label > span {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-priorities input:not(:checked) + label > span:nth-child(4) {
|
|
||||||
filter: grayscale(100%) opacity(60%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-dates {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 5.5em auto;
|
|
||||||
column-gap: .5em;
|
|
||||||
row-gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-dates > label {
|
|
||||||
grid-column: 1;
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-dates > input, .tasks-modal-dates > code {
|
|
||||||
grid-column: 2;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-dates > code {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-dates > div {
|
|
||||||
grid-column-start: 1;
|
|
||||||
grid-column-end: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-status {
|
|
||||||
padding-bottom: 6px;
|
|
||||||
margin-bottom: -16px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-error {
|
|
||||||
border: 1px solid red !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal-warning {
|
|
||||||
color: var(--text-warning) !important;
|
|
||||||
background-color: rgba(var(--background-modifier-warning-rgb), 0.2) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-modal button:disabled {
|
|
||||||
pointer-events: none !important;
|
|
||||||
opacity: 0.3 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 649px) {
|
|
||||||
.tasks-modal-priorities {
|
|
||||||
grid-template-columns: 4em 7.5em 5em;
|
|
||||||
margin-bottom: -10px;
|
|
||||||
}
|
|
||||||
.tasks-modal-priorities > label {
|
|
||||||
grid-row: 1 / span 7;
|
|
||||||
}
|
|
||||||
.tasks-modal-dates {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
.tasks-modal-dates > label {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.tasks-modal-dates > input, .tasks-modal-dates > code {
|
|
||||||
grid-column: 1;
|
|
||||||
}
|
|
||||||
.tasks-modal-dates > div {
|
|
||||||
grid-column-end: 1;
|
|
||||||
}
|
|
||||||
.tasks-modal-status {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 399px) {
|
|
||||||
.tasks-modal-priorities {
|
|
||||||
grid-template-columns: 4em auto;
|
|
||||||
}
|
|
||||||
.tasks-modal-priorities > label {
|
|
||||||
grid-row: 1 / span 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 259px) {
|
|
||||||
.tasks-modal-priorities {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.tasks-modal-priorities > label {
|
|
||||||
grid-row: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**------------------------------------------------------------------------
|
|
||||||
** SETTINGS
|
|
||||||
*------------------------------------------------------------------------**/
|
|
||||||
|
|
||||||
.tasks-settings-is-invalid {
|
|
||||||
/* Dark red text on pale background*/
|
|
||||||
color: var(--text-error) !important;
|
|
||||||
background-color: rgba(var(--background-modifier-error-rgb), 0.2) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.tasks-settings .additional {
|
|
||||||
margin: 6px 12px;
|
|
||||||
}
|
|
||||||
.tasks-settings .additional > .setting-item {
|
|
||||||
border-top: 0;
|
|
||||||
padding-top: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.tasks-settings details > summary {
|
|
||||||
outline: none;
|
|
||||||
display: block !important;
|
|
||||||
list-style: none !important;
|
|
||||||
list-style-type: none !important;
|
|
||||||
min-height: 1rem;
|
|
||||||
border-top-left-radius: 0.1rem;
|
|
||||||
border-top-right-radius: 0.1rem;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-settings details > summary::-webkit-details-marker,
|
|
||||||
.tasks-settings details > summary::marker {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-settings details > summary > .collapser {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 8px;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-settings details > summary > .collapser > .handle {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
transition: transform 0.25s;
|
|
||||||
background-color: currentColor;
|
|
||||||
-webkit-mask-repeat: no-repeat;
|
|
||||||
mask-repeat: no-repeat;
|
|
||||||
-webkit-mask-size: contain;
|
|
||||||
mask-size: contain;
|
|
||||||
-webkit-mask-image: var(--tasks-details-icon);
|
|
||||||
mask-image: var(--tasks-details-icon);
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-settings details[open] > summary > .collapser > .handle {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-nested-settings .setting-item {
|
|
||||||
border: 0px;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
.tasks-nested-settings {
|
|
||||||
padding-bottom: 18px;
|
|
||||||
}
|
|
||||||
.tasks-nested-settings[open] .setting-item-heading,
|
|
||||||
.tasks-nested-settings:not(details) .setting-item-heading {
|
|
||||||
border-top: 0px;
|
|
||||||
border-bottom: 1px solid var(--background-modifier-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tasks-settings .row-for-status {
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
16
.obsidian/plugins/update-time-on-edit/data.json
vendored
16
.obsidian/plugins/update-time-on-edit/data.json
vendored
|
|
@ -17,7 +17,7 @@
|
||||||
"templates/base-note.md": "23eff811614efdfb18252c14d7d548b50a707dcfda5f4bf6e0259020f1eeb80a",
|
"templates/base-note.md": "23eff811614efdfb18252c14d7d548b50a707dcfda5f4bf6e0259020f1eeb80a",
|
||||||
"notes/testo.md": "24df1da31f19afae3f434032b447e804a8bcbdeeb1b270c6d04f28bfba5583fb",
|
"notes/testo.md": "24df1da31f19afae3f434032b447e804a8bcbdeeb1b270c6d04f28bfba5583fb",
|
||||||
"notes/North Start.md": "662704939ce34782d6578cd8d91d5d7d738de19ce5eb34196f71733744bc1286",
|
"notes/North Start.md": "662704939ce34782d6578cd8d91d5d7d738de19ce5eb34196f71733744bc1286",
|
||||||
"README.md": "a6a254c8e6a7d09434ac79e2682b2aca0614d7dbd45dc7bcea103d6f92968c0a",
|
"README.md": "a2dec872f00c5115d438a1213c95cda54341641e25612e8368d77769b9b510ce",
|
||||||
"notes/Devlog.md": "8796c41169b072acea9ef97211e294ba7b464ccffabc1259c7763440fea7a63e",
|
"notes/Devlog.md": "8796c41169b072acea9ef97211e294ba7b464ccffabc1259c7763440fea7a63e",
|
||||||
"01. Projects/Obtener pasaporte/Obtener pasaporte.md": "f3c1769ca0f40f87c41954c48b4cc791cf77dc22422e15a7005a880d9b030de9",
|
"01. Projects/Obtener pasaporte/Obtener pasaporte.md": "f3c1769ca0f40f87c41954c48b4cc791cf77dc22422e15a7005a880d9b030de9",
|
||||||
"02. Areas/Dotfiles/dotfiles tasks.md": "85c72a54844c201397a839d9394aa74896f3e76c2127b2325ce2e480a1fa15f9",
|
"02. Areas/Dotfiles/dotfiles tasks.md": "85c72a54844c201397a839d9394aa74896f3e76c2127b2325ce2e480a1fa15f9",
|
||||||
|
|
@ -45,10 +45,10 @@
|
||||||
"03. Resources/Development/Search for a bug.md": "627a609a636453bd9de584ad559ea83338076fe656c08c90604f6551f79cab20",
|
"03. Resources/Development/Search for a bug.md": "627a609a636453bd9de584ad559ea83338076fe656c08c90604f6551f79cab20",
|
||||||
"03. Resources/Development/Feature shipment checklist.md": "e6667e273f6553b4418039564f02dc51d5e83c5455d202cae4daf333914911be",
|
"03. Resources/Development/Feature shipment checklist.md": "e6667e273f6553b4418039564f02dc51d5e83c5455d202cae4daf333914911be",
|
||||||
"03. Resources/Development/Iframes.md": "858ffe616925f94e6bfca207282649b111f134e30c67a76ddd0479c4f6193761",
|
"03. Resources/Development/Iframes.md": "858ffe616925f94e6bfca207282649b111f134e30c67a76ddd0479c4f6193761",
|
||||||
"02. Areas/Escape Latam/Canada.md": "974bdb92354ff2d46e67f524390bce477c8b0f753012f4f86eb0d4291b10a6ce",
|
"02. Areas/Escape Latam/Canada.md": "6f7ca6695ad9eb07f2fa2583a7eb893db71badbb9f01968fe49b31998e35c66e",
|
||||||
"02. Areas/Escape Latam/Comparación de Paises.md": "6fb41dde50e73d696948be100340f951fc490f40cbcdda45584719fd7ba57194",
|
"02. Areas/Escape Latam/Comparación de Paises.md": "6fb41dde50e73d696948be100340f951fc490f40cbcdda45584719fd7ba57194",
|
||||||
"02. Areas/Escape Latam/Escapar de Latam.md": "4ac856a52471f5eb6923790a96bbbf9daa867137cf9b8add09f498ba87e4469e",
|
"02. Areas/Escape Latam/Escapar de Latam.md": "4ac856a52471f5eb6923790a96bbbf9daa867137cf9b8add09f498ba87e4469e",
|
||||||
"02. Areas/Escape Latam/New Zeldand.md": "c46e7d6cb08da2a7d5500640abc560f5db37dd056561420bce56df1c6eb485c7",
|
"02. Areas/Escape Latam/New Zeldand.md": "28b70d975aadddcaa52dde2ca3a32546b508bec41dece7ec475ba5a2b066d897",
|
||||||
"notes/Good Enough.md": "0bb2e063f1f416af89a28b03bee9f40b0b3cbb170167efea08ad1fbb13751c58",
|
"notes/Good Enough.md": "0bb2e063f1f416af89a28b03bee9f40b0b3cbb170167efea08ad1fbb13751c58",
|
||||||
"notes/Git.md": "c94e17e08d108bdfb69d3a1bda02bcb74e4e02f1bb827c8c518d0c4e299fdc7a",
|
"notes/Git.md": "c94e17e08d108bdfb69d3a1bda02bcb74e4e02f1bb827c8c518d0c4e299fdc7a",
|
||||||
"02. Areas/Food/recipes/Fritos de Jurel.md": "4808e20673ac51ab40904f3f0c46e44f4935eb303fdabb6fe4ecf73f835ece49",
|
"02. Areas/Food/recipes/Fritos de Jurel.md": "4808e20673ac51ab40904f3f0c46e44f4935eb303fdabb6fe4ecf73f835ece49",
|
||||||
|
|
@ -67,10 +67,10 @@
|
||||||
"99. Archives/Setup Obsidian/Foo.md": "91a207af114d10d6808497e9ba4560f29cab32a51522e8a82d0adcd422d75b5d",
|
"99. Archives/Setup Obsidian/Foo.md": "91a207af114d10d6808497e9ba4560f29cab32a51522e8a82d0adcd422d75b5d",
|
||||||
"99. Archives/Setup Obsidian/Objective.md": "9fde8bbc47587e36690dbf3a2c61e1c405224728663bb0400d2c89ab6646e197",
|
"99. Archives/Setup Obsidian/Objective.md": "9fde8bbc47587e36690dbf3a2c61e1c405224728663bb0400d2c89ab6646e197",
|
||||||
"99. Archives/Setup Obsidian/README.md": "ea86a009119fb8eec4043e7a309b2e6cc149430046dbce923905299f3d0cdc56",
|
"99. Archives/Setup Obsidian/README.md": "ea86a009119fb8eec4043e7a309b2e6cc149430046dbce923905299f3d0cdc56",
|
||||||
"01. Projects/Página Personal/README.md": "74e5e05cbf4dfc739bcb5f6e70add2267f3d9f6c9a1813d1bb4e136707694ecc",
|
"01. Projects/Página Personal/README.md": "bd8a194074279fe701674ef0d04ce7388488d53f4b4240f9eccb39accce3c0ef",
|
||||||
"01. Projects/Página Personal/CI-CD.md": "47301f139c7ad4b6cb4adb39486808e4dc12e71c2f3d1a0d04b67b61880922a1",
|
"01. Projects/Página Personal/CI-CD.md": "47301f139c7ad4b6cb4adb39486808e4dc12e71c2f3d1a0d04b67b61880922a1",
|
||||||
"01. Projects/Página Personal/Components/Table.md": "39d18aeaee771d70d477c0627e1ac5d9006428b695edd527d3d12ce3edea756e",
|
"01. Projects/Página Personal/Components/Table.md": "39d18aeaee771d70d477c0627e1ac5d9006428b695edd527d3d12ce3edea756e",
|
||||||
"01. Projects/Página Personal/Pages/Landing Page.md": "418a3b2f5b67ba6babe1ace2ea5a0ebe651b3acae0a1147807dabcb01b5a3a01",
|
"01. Projects/Página Personal/Pages/Landing Page.md": "506a338e996c043b5d9c057cb1a373f33bb2209b926646bd317327b47842a7fe",
|
||||||
"01. Projects/Página Personal/Pages/Blog entry.md": "b29ce28c50f4a32647ef4a7ef492e60b62c3e9ea7ebe862814c8a5c4cdc62135",
|
"01. Projects/Página Personal/Pages/Blog entry.md": "b29ce28c50f4a32647ef4a7ef492e60b62c3e9ea7ebe862814c8a5c4cdc62135",
|
||||||
"01. Projects/Página Personal/Pages/Blog entry list.md": "b29ce28c50f4a32647ef4a7ef492e60b62c3e9ea7ebe862814c8a5c4cdc62135",
|
"01. Projects/Página Personal/Pages/Blog entry list.md": "b29ce28c50f4a32647ef4a7ef492e60b62c3e9ea7ebe862814c8a5c4cdc62135",
|
||||||
"01. Projects/Página Personal/Pages/Portafolio List.md": "2ecba1c2632dac7515e2d1e7239370913e1f285189c082ae5f257c5226009aeb",
|
"01. Projects/Página Personal/Pages/Portafolio List.md": "2ecba1c2632dac7515e2d1e7239370913e1f285189c082ae5f257c5226009aeb",
|
||||||
|
|
@ -80,6 +80,10 @@
|
||||||
"01. Projects/Página Personal/Global Apllication.md": "9aee7ddf3b1499bc04421048934a5946e27e27284081104c376d4cca2524ba4b",
|
"01. Projects/Página Personal/Global Apllication.md": "9aee7ddf3b1499bc04421048934a5946e27e27284081104c376d4cca2524ba4b",
|
||||||
"01. Projects/Página Personal/Components/Lightbox.md": "bdcfa890e92e9bc82312e3d578025664738ef83b85daa410b07668dafbce9e75",
|
"01. Projects/Página Personal/Components/Lightbox.md": "bdcfa890e92e9bc82312e3d578025664738ef83b85daa410b07668dafbce9e75",
|
||||||
"01. Projects/Página Personal/Components/TOC.md": "172a80f929427b55617b3af3e4a8148961f8e2e21f7ede323baee0123daa97f3",
|
"01. Projects/Página Personal/Components/TOC.md": "172a80f929427b55617b3af3e4a8148961f8e2e21f7ede323baee0123daa97f3",
|
||||||
"02. Areas/Exersice/Misc.md": "1f94b19612f1e9dbccad4259c3e3be3d982e59cf844adac0515aaf351bb98f03"
|
"02. Areas/Exersice/Misc.md": "1f94b19612f1e9dbccad4259c3e3be3d982e59cf844adac0515aaf351bb98f03",
|
||||||
|
"04. Periodic/01. Daily/2024-02-26.md": "7fb073a9e68f1c16667c5f935d9259af15db1a293f85ff80cff0fb1471a262f1",
|
||||||
|
"03. Resources/Development/CSS and Component Libraries.md": "412afe81d1982fa69052f22fa8297b679fbe7be8989b85aac9650a66264c9204",
|
||||||
|
"03. Resources/Design/Layouts.md": "e6a02df0d843e3e9fdf03013a7e220d58765f7fc0a2a34d3ff20b4c2584ad244",
|
||||||
|
"03. Resources/Design/Design.md": "58c8ad37088e206dd4dff3b5162388f970d1cfa996e0b7ac8e0cd9cbc2177716"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
---
|
---
|
||||||
created: 2024-02-24 12:48
|
created: 2024-02-24 12:48
|
||||||
updated: 2024-02-24 13:16
|
updated: 2024-02-29 18:38
|
||||||
---
|
---
|
||||||
## TODO
|
## Brainstorm
|
||||||
|
|
||||||
- [ ] Cambiar componente lightbox para remover Lightgallery
|
- Sections:
|
||||||
- LightGallery es de pago realmente, por lo que necesito una licencia
|
- Hero with short description and image
|
||||||
- [ ] Buscar ejemplos de animaciones que podría integrar
|
- _featured work_, a selection of projects from portafolio
|
||||||
- [ ] Aplicar [View Transition](https://docs.astro.build/en/guides/view-transitions/)
|
- content section with quick links to games and blog (hidden while wip)
|
||||||
- [ ] Redesign page
|
_"What I have been up to..._
|
||||||
- hide lists
|
- detail description of what I'm interested in with links to full curriculum
|
||||||
- hide blog and games from navbar
|
- Contact page
|
||||||
- [ ] Redactar _"about me page"_
|
- Linkedin
|
||||||
- [ ] Conseguir una foto decente mía
|
- Github
|
||||||
- [ ] Add E2E tests
|
- email
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- https://www.pinterest.cl/pin/976084919228483905/
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
|
|
||||||
131447
01. Projects/Página Personal/Pages/Landing Page.pdf
Normal file
131447
01. Projects/Página Personal/Pages/Landing Page.pdf
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,19 +1,10 @@
|
||||||
---
|
---
|
||||||
created: 2024-02-24 12:29
|
created: 2024-02-24 12:29
|
||||||
updated: 2024-02-24 13:07
|
updated: 2024-02-29 17:21
|
||||||
status: Backlog
|
status: Backlog
|
||||||
---
|
---
|
||||||
# Página Personal
|
# Página Personal
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
```tasks
|
|
||||||
(path includes 01. Projects/Página Personal) AND (filename does not include {{query.file.filename}})
|
|
||||||
group by function task.file.pathWithoutExtension.split('/').slice(2).join("/")
|
|
||||||
sort by urgency
|
|
||||||
hide backlink
|
|
||||||
```
|
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- Cool websites for inspiration:
|
- Cool websites for inspiration:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,17 @@
|
||||||
---
|
---
|
||||||
id: 479b9e29-c514-42b2-a086-f1290936cb57
|
id: 479b9e29-c514-42b2-a086-f1290936cb57
|
||||||
created: 2024-02-06 14:20
|
created: 2024-02-06 14:20
|
||||||
updated: 2024-02-18 15:29
|
updated: 2024-02-26 18:34
|
||||||
---
|
---
|
||||||
|
## Standard hours of work
|
||||||
|
|
||||||
|
As an employee or [student intern](https://www.canada.ca/en/services/jobs/workplace/federal-labour-standards/interns.html), your standard hours of work are:
|
||||||
|
|
||||||
|
- 8 hours in a day (any period of 24 consecutive hours)
|
||||||
|
- 40 hours in a week (the period between midnight on Saturday and midnight on the Saturday that immediately follows)
|
||||||
|
|
||||||
|
### Maximum hours of work
|
||||||
|
|
||||||
|
In most cases, the maximum hours of work allowable in a week is 48.
|
||||||
|
|
||||||
|
- [source](https://www.canada.ca/en/services/jobs/workplace/federal-labour-standards/work-hours.html)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
---
|
---
|
||||||
created: 2024-02-06 14:17
|
created: 2024-02-06 14:17
|
||||||
updated: 2024-02-18 15:29
|
updated: 2024-02-26 18:31
|
||||||
---
|
---
|
||||||
## Work & Holiday
|
## Work & Holiday
|
||||||
|
|
||||||
Último ciclo de postulación fue en Octubre 2023, avisan con al menos 1 mes de anticipación
|
Último ciclo de postulación fue en Octubre 2023, avisan con al menos 1 mes de anticipación
|
||||||
|
|
||||||
|
## Maximum number of hours
|
||||||
|
|
||||||
|
Employment agreements must fix the maximum number of hours to be worked by the employee at no more than 40 per week (not including overtime) unless the employer and employee agree otherwise.
|
||||||
|
|
||||||
|
If the maximum number of hours (not including overtime) are less than 40, the employer and employee must try to fix the hours so they are worked on no more than five days of the week.
|
||||||
|
|
||||||
|
- [source](https://www.employment.govt.nz/hours-and-wages/hours-of-work/#scrollto-maximum-number-of-hours)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
---
|
||||||
|
created: 2023-08-17 10:05
|
||||||
|
updated: 2024-02-29 18:36
|
||||||
|
---
|
||||||
Diseñar está completamente fuera de mi zona de confort, así que estudiar como hacer, y hacer el esfuerzo de planear como diseñar la página antes de tirarme de hocico a hacerlo ha sido una experiencia bastante satisfactoria
|
Diseñar está completamente fuera de mi zona de confort, así que estudiar como hacer, y hacer el esfuerzo de planear como diseñar la página antes de tirarme de hocico a hacerlo ha sido una experiencia bastante satisfactoria
|
||||||
|
|
||||||
Pensar que debo realizar, que quiero comunicar y como lo quiero comunicar ha enrutado el diseño y permitiendo que sea más facil
|
Pensar que debo realizar, que quiero comunicar y como lo quiero comunicar ha enrutado el diseño y permitiendo que sea más facil
|
||||||
|
|
@ -57,3 +61,6 @@ Reference:
|
||||||
|
|
||||||
- [Material Design - UI](https://m2.material.io/design/environment/elevation.html)
|
- [Material Design - UI](https://m2.material.io/design/environment/elevation.html)
|
||||||
- [Material Design - Dark Theme](https://m2.material.io/design/color/dark-theme.html)
|
- [Material Design - Dark Theme](https://m2.material.io/design/color/dark-theme.html)
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
6
03. Resources/Design/Layouts.md
Normal file
6
03. Resources/Design/Layouts.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
created: 2024-02-29 18:36
|
||||||
|
updated: 2024-02-29 18:36
|
||||||
|
---
|
||||||
|
## Layouts
|
||||||
|
- [How to Properly Layout A Website (For Beginners)](https://www.youtube.com/watch?v=3C_22eBWpjg&t=604s)
|
||||||
8
03. Resources/Development/CSS and Component Libraries.md
Normal file
8
03. Resources/Development/CSS and Component Libraries.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
created: 2024-02-28 13:18
|
||||||
|
updated: 2024-02-28 13:20
|
||||||
|
---
|
||||||
|
|
||||||
|
| Library | Description |
|
||||||
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
|
| [shadcn/ui](https://ui.shadcn.com/) | Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source. |
|
||||||
9
04. Periodic/01. Daily/2024-02-26.md
Normal file
9
04. Periodic/01. Daily/2024-02-26.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
created: 2024-02-26 14:01
|
||||||
|
updated: 2024-02-26 14:03
|
||||||
|
---
|
||||||
|
- [Lightbox](Lightbox.md)
|
||||||
|
- Se intenta solucionar el issue de compilación de LightGallery, pero se gastan 2 hrs en vano
|
||||||
|
- Buscar alternativas
|
||||||
|
- Otras librerías
|
||||||
|
- Otros layout para las imágenes
|
||||||
11
README.md
11
README.md
|
|
@ -1,16 +1,7 @@
|
||||||
---
|
---
|
||||||
created: 2024-02-20 12:23
|
created: 2024-02-20 12:23
|
||||||
updated: 2024-02-23 13:20
|
updated: 2024-02-29 17:25
|
||||||
---
|
---
|
||||||
# docs
|
# docs
|
||||||
|
|
||||||
Markdown files for general purpose
|
Markdown files for general purpose
|
||||||
|
|
||||||
## Tasks
|
|
||||||
```tasks
|
|
||||||
not done
|
|
||||||
path does not include 99. Archives
|
|
||||||
group by function task.file.folder.split('/').at(0)
|
|
||||||
group by function task.file.folder.split('/').at(1)
|
|
||||||
sort by urgency
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,598 @@
|
||||||
|
---
|
||||||
|
id: 085bfd7c-d52a-11ee-bfc7-b34a261d031c
|
||||||
|
title: |
|
||||||
|
How to Learn the Hard Parts of React – and Tips to Conquer Them
|
||||||
|
status: ARCHIVED
|
||||||
|
tags:
|
||||||
|
- read-later
|
||||||
|
- RSS
|
||||||
|
date_added: 2024-02-26 18:07:53
|
||||||
|
url_omnivore: |
|
||||||
|
https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244
|
||||||
|
url_original: |
|
||||||
|
https://www.freecodecamp.org/news/hard-parts-of-react/
|
||||||
|
---
|
||||||
|
|
||||||
|
# How to Learn the Hard Parts of React – and Tips to Conquer Them
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
|
||||||
|
The first instinct for many developers when faced with creating dynamic lists is to use the index property as the key. It seems like a convenient solution, as the index provides a unique identifier for each element in the array – but it isn’t the best approach for the following reasons:
|
||||||
|
|
||||||
|
* **Non-Persistent**: If the order or number of items changes, React may get confused. For example, if an item is added or removed from the beginning of the list, all the subsequent indices change, causing potential re-rendering issues.
|
||||||
|
* **Array Mutations**: Operations like sorting or filtering can alter the order of items, breaking the association between the index and the actual item.
|
||||||
|
* **Performance Concerns**: React relies on keys for efficient updates. Using the index as a key might impact performance when dealing with large lists or frequent updates.
|
||||||
|
|
||||||
|
Some of the better alternatives include:
|
||||||
|
|
||||||
|
* **Use a Unique ID**: If each item in your array has a unique identifier, such as an `id` property, use that as the key.
|
||||||
|
|
||||||
|
[source](https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244#e912d65e-4c82-41f1-94d4-56c151254c3e)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Generate a Unique Key: In cases where items lack a natural unique identifier, consider using a function like `crypto.randomUUID()` to generate a unique key.
|
||||||
|
|
||||||
|
[source](https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244#9074fe2d-d95d-4fc6-af45-be052bb24de5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
To ensure your component behaves as expected and follows React's principles, always use the setter function (`setNames`) to update the state.
|
||||||
|
|
||||||
|
[source](https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244#a42adf04-e7ec-4612-a7ea-c179bfce9163)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
To safeguard your component from unexpected errors, incorporate optional chaining (`?.`) when accessing nested properties in API data.
|
||||||
|
|
||||||
|
[source](https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244#7ef6781d-7b8b-496d-bd2d-2974995be502)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
* **Put data outside components**: Move things like lists and groups of information outside the main part of a component when possible. This helps avoid extra updates and makes it simpler to handle data without using special functions like `useCallback`.
|
||||||
|
* **Be careful with `React.memo`**: Using `React.memo` can help your components run better, but it's not always needed. If a component changes a lot with new information, using `React.memo` might not be as helpful. Use it wisely.
|
||||||
|
* **Create your own custom React hooks**: I also like making my own special tools with custom React hooks. It's a bit advanced, but it helps keep my code neat and organized.
|
||||||
|
|
||||||
|
[source](https://omnivore.app/me/how-to-learn-the-hard-parts-of-react-and-tips-to-conquer-them-18de8db4244#eb5d0b4b-a153-4551-a3a4-522a590854b5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Original
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Have you started learning React, only to face bugs that made you contemplate a career in goat herding? Don't worry – we've all been there.
|
||||||
|
|
||||||
|
In this guide, you'll join me on a quest through the quirky wonders of React. I'll help you navigate the perplexing moments, ensuring you never have to ask yourself, "What’s up with React?"
|
||||||
|
|
||||||
|
Whether you're a seasoned React adventurer or unearthing the mysteries of virtual DOMs, fear not. I'm here to share the tales of my early struggles, demystify the enigmatic bugs, and pave the way for a smoother journey.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
* Fundamentals of HTML and CSS
|
||||||
|
* Fundamentals of ES6 JavaScript and React
|
||||||
|
|
||||||
|
## ****What We'll Cover:**
|
||||||
|
|
||||||
|
1. [Quick Recap of React Fundamentals](#what-we-ll-cover-)
|
||||||
|
– [Components: The Web Building Blocks](#components-the-web-building-blocks)
|
||||||
|
– [JSX: Where HTML Meets JavaScript](#jsx-where-html-meets-javascript)
|
||||||
|
– [State and Props: The Dynamic Duo](#state-and-props-the-dynamic-duo)
|
||||||
|
2. [The Good, the Bad, and the Challenging Parts of React](#the-good-the-bad-and-the-challenging-parts-of-react)
|
||||||
|
– [The Good Parts of React](#the-good-parts-of-react)
|
||||||
|
– [The Bad Parts of React](#the-bad-parts-of-react)
|
||||||
|
– [The Challenging Parts of React](#the-challenging-parts-of-react)
|
||||||
|
– [Key Prop Mishaps](#key-prop-mishaps)
|
||||||
|
– [Mutating States Directly](#mutating-states-directly)
|
||||||
|
– [Mysterious Bugs with Conditional Rendering](#mysterious-bugs-with-conditional-rendering)
|
||||||
|
– [Ignoring Dependency Arrays in React Hooks](#ignoring-dependency-arrays-in-react-hooks)
|
||||||
|
– [Neglecting Optional Chaining for API Data](#neglecting-optional-chaining-for-api-data)
|
||||||
|
– [Ignoring React Fragments for Grouping JSX Elements](#ignoring-react-fragments-for-grouping-jsx-elements)
|
||||||
|
3. [Opinionated Approaches to React](#opinionated-approaches-to-react)
|
||||||
|
4. [Wrapping Up the Quirky Journey with React](#wrapping-up-the-quirky-journey-with-react)
|
||||||
|
|
||||||
|
## Quick Recap of React Fundamentals
|
||||||
|
|
||||||
|
The React library revolves around 3 building blocks: Components, JSX, and State & Props.
|
||||||
|
|
||||||
|
### Components: The Web Building Blocks
|
||||||
|
|
||||||
|
Imagine components as the LEGO bricks of your user interface—a single, reusable piece that contributes to the grand structure. They encapsulate functionality, styling, and behavior, making your UI both modular and scalable.
|
||||||
|
|
||||||
|
From a simple button to an elaborate sidebar, components are the heart and soul of React development.
|
||||||
|
|
||||||
|
### JSX: Where HTML Meets JavaScript
|
||||||
|
|
||||||
|
JSX, or JavaScript XML, may seem like an odd fusion of HTML and JavaScript at first, but it’s quite straightforward. It's the secret sauce that makes React's syntax so expressive and dynamic.
|
||||||
|
|
||||||
|
With JSX, you write your UI components using a syntax that resembles HTML, but underneath, it's pure JavaScript.
|
||||||
|
|
||||||
|
### State and Props: The Dynamic Duo
|
||||||
|
|
||||||
|
The dynamic duo of state and props bring React pages to life as they add interactivity to your web applications.
|
||||||
|
|
||||||
|
#### State: Granting Memory to Components
|
||||||
|
|
||||||
|
State provides memory to components, allowing them to remember past events and alter their behavior over time. It's the key to making your UI responsive and dynamic.
|
||||||
|
|
||||||
|
Picture a form that remembers the user's input or a counter that increments with each click. That's the magic of state.
|
||||||
|
|
||||||
|
#### Props: Enabling Communication
|
||||||
|
|
||||||
|
Props (short for properties) facilitate communication between components. They allow parent components to pass data down to their children, creating a seamless flow of information.
|
||||||
|
|
||||||
|
Think of props as messengers, ensuring that each component knows its role and receives the necessary information to perform it.
|
||||||
|
|
||||||
|
## The Good, the Bad, and the Puzzling Parts of React
|
||||||
|
|
||||||
|
Before we delve into the puzzling aspects of React, it's essential to shine a spotlight on the treasures that make React a true hero in your arsenal.
|
||||||
|
|
||||||
|
### The Good Parts of React
|
||||||
|
|
||||||
|
#### Virtual DOM and its Advantages
|
||||||
|
|
||||||
|
The virtual DOM is a revolutionary concept that gives React its speed and efficiency.
|
||||||
|
|
||||||
|
When changes occur in your app, React doesn't immediately update the actual DOM. Instead, it works with a lightweight copy, the Virtual DOM, making minimal, lightning-fast adjustments. This not only optimizes performance but also provides a smoother user experience.
|
||||||
|
|
||||||
|
```reasonml
|
||||||
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
|
<App />
|
||||||
|
);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This process leverages [React's diffing algorithm](https://legacy.reactjs.org/docs/reconciliation.html) in the Virtual DOM. It identifies the minimal set of changes needed in the actual DOM to reflect the updated state.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Explaining how React updates the UI using the virtual DOM
|
||||||
|
|
||||||
|
#### Reusable Components
|
||||||
|
|
||||||
|
In React, the guiding principle is reusability. Components, the fundamental building blocks we discussed above, can be crafted and employed across your application. This not only fosters a modular and organized code structure but also frees you from the burden of reinventing the wheel.
|
||||||
|
|
||||||
|
```hsp
|
||||||
|
// Reusable Button Component
|
||||||
|
const Button = ({ label, onClick }) => (
|
||||||
|
<button onClick={onClick}>{label}</button>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
<Button label="Click me" onClick={() => console.log("Button Clicked")} />
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### One-way Data Binding for a Predictable Flow
|
||||||
|
|
||||||
|
React enforces a unidirectional data flow, ensuring predictability and maintainability.
|
||||||
|
|
||||||
|
Parent components convey data down to their children through props, and any modifications are overseen by the parent component. This one-way street prevents the chaos with 2-way data binding seen in other frameworks.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
const ParentComponent = () => {
|
||||||
|
const [data, setData] = useState("Hello from Parent!");
|
||||||
|
|
||||||
|
return <ChildComponent data={data} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ChildComponent = ({ data }) => <div>{data}</div>;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### The Bad Parts of React
|
||||||
|
|
||||||
|
There are some parts of React that aren't ideal, though. Let's go through them briefly now so you can be aware of them.
|
||||||
|
|
||||||
|
#### Steep Learning Curve for Beginners
|
||||||
|
|
||||||
|
Starting with React can be tough, especially if you're new to web development. Concepts like JSX, components, and state management might seem like a maze. But don't worry! With some practice and patience, it gets easier, and React becomes more familiar.
|
||||||
|
|
||||||
|
#### JSX Might Puzzle You at First
|
||||||
|
|
||||||
|
JSX, the special mix of HTML and JavaScript, can be a bit confusing at the beginning. It's like learning a new language that blends the two. But as you get the hang of it, you'll see how it makes your code shorter and clearer.
|
||||||
|
|
||||||
|
#### State Management Challenges
|
||||||
|
|
||||||
|
Using state in React is powerful, but it can also be tricky. Handling state across lots of different pieces, especially in big projects, can create complex setups and potential problems. Luckily, tools like [Redux](https://redux.js.org/) exist to help manage this complexity.
|
||||||
|
|
||||||
|
## The Challenging Parts of React
|
||||||
|
|
||||||
|
### Key Prop Mishaps
|
||||||
|
|
||||||
|
When building your applications, you may often have repeating elements which show similar information or share the same styles. The logical step would be to loop over them to create a list of elements.
|
||||||
|
|
||||||
|
```xquery
|
||||||
|
function ListComponent() {
|
||||||
|
const people = [{ name: "Mitchelle" }, { name: "July" }, { name: "David" }];
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{/ Looping over the people array to create list items /}
|
||||||
|
{people.map((person) => (
|
||||||
|
<li>{person.name}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Everything seems fine until you notice a warning in your console or, worse, strange behaviour in how your list renders.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The console an error due to missing key prop
|
||||||
|
|
||||||
|
React uses keys to update and reorder elements in a list. When you forget to provide a key prop or if the keys are not unique, React gets a bit lost. It's like trying to keep track of items in the array without any specific identifiers – things get mixed up, and you might end up with unexpected bugs in your UI.
|
||||||
|
|
||||||
|
#### How to solve it
|
||||||
|
|
||||||
|
==The first instinct for many developers when faced with creating dynamic lists is to use the index property as the key. It seems like a convenient solution, as the index provides a unique identifier for each element in the array== ==– but it isn’t the best approach for the following reasons:==
|
||||||
|
|
||||||
|
* **==Non-Persistent==**==: If the order or number of items changes, React may get confused. For example, if an item is added or removed from the beginning of the list, all the subsequent indices change, causing potential re-rendering issues.==
|
||||||
|
* **==Array Mutations==**==: Operations like sorting or filtering can alter the order of items, breaking the association between the index and the actual item.==
|
||||||
|
* **==Performance Concerns==**==: React relies on keys for efficient updates. Using the index as a key might impact performance when dealing with large lists or frequent updates.==
|
||||||
|
|
||||||
|
==Some of the better alternatives include:==
|
||||||
|
|
||||||
|
* **==Use a Unique ID==**==: If each item in your array has a unique identifier, such as an== `==id==` ==property, use that as the key.==
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
{people.map((person) => (
|
||||||
|
<li key={person.id}>{person.name}</li>
|
||||||
|
))}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
* ==Generate a Unique Key: In cases where items lack a natural unique identifier, consider using a function like== `==crypto====.randomUUID====()==` ==to generate a unique key.==
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
{people.map((person) => (
|
||||||
|
<li key={crypto.randomUUID()}>{person.name}</li>
|
||||||
|
))}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
By choosing one of these alternatives, you provide React with stable and unique keys, helping it manage and update your dynamic lists,
|
||||||
|
|
||||||
|
**Note**: You may be thinking “If `crypto.randomUUID` generates a unique ID, (`Math.random()` \* some big number) would work the same, right”?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Nope gif
|
||||||
|
|
||||||
|
`Math.random()` could also suffice as a key, but it's a bad idea because the generated keys won't be stable across re-renders, leading to potential performance issues and rendering inconsistencies.
|
||||||
|
|
||||||
|
### Mutating States Directly
|
||||||
|
|
||||||
|
Imagine you're working on a component that manages an array of names. Rather than using the appropriate setter method to update the state, you decide to directly mutate the state.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const MutableStateComponent = () => {
|
||||||
|
const [names, setNames] = useState(["David", "John", "Steph", "Anthony"]);
|
||||||
|
|
||||||
|
const removeLastName = () => {
|
||||||
|
console.log(names);
|
||||||
|
// Direct mutation of state using pop()
|
||||||
|
names.pop();
|
||||||
|
setNames(names); // This won't trigger a re-render
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>Names: {names.join(", ")}</p>
|
||||||
|
<button onClick={removeLastName}>Remove Last Name</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
To your surprise, the UI doesn't update as expected, and you find yourself stuck in a scenario where the list of names seems frozen. Make no mistake, the array is getting updated as seen below:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Array getting mutated with UI being updated
|
||||||
|
|
||||||
|
#### What's the Problem?
|
||||||
|
|
||||||
|
React relies on an immutable state for efficient updates, and when you bypass this mechanism, it disrupts the unidirectional data flow.
|
||||||
|
|
||||||
|
In this case, using `pop()` mutates the original array in place, and React loses track of the changes. This leads to an inaccurate rendering of the component.
|
||||||
|
|
||||||
|
#### How to Solve it
|
||||||
|
|
||||||
|
==To ensure your component behaves as expected and follows React's principles, always use the setter function (==`==setNames==`==) to update the state.==
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const MutableStateComponent = () => {
|
||||||
|
const [names, setNames] = useState(["David", "John", "Steph", "Anthony"]);
|
||||||
|
|
||||||
|
const removeLastName = () => {
|
||||||
|
// Use setNames to update state
|
||||||
|
setNames((prevNames) => prevNames.slice(0, -1));
|
||||||
|
console.log(names);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>Names: {names.join(", ")}</p>
|
||||||
|
<button onClick={removeLastName}>Remove Last Name</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
By using `setNames` and creating a new array with the desired changes (in this case, using `slice` to remove the last element), you ensure that React can accurately track and update the state, resulting in the expected UI behavior.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Result of mutating states with the correct method
|
||||||
|
|
||||||
|
### Mysterious Bugs with Conditional Rendering
|
||||||
|
|
||||||
|
Conditional rendering, while powerful, can introduce subtle bugs when not handled with care. Understanding common pitfalls, particularly those related to truthy and falsy evaluations, is crucial for preventing mysterious rendering behaviour.
|
||||||
|
|
||||||
|
Consider the following example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const IncorrectConditionalComponent = ({ showContent }) => (
|
||||||
|
{showContent && <div>Show me if true!</div>}
|
||||||
|
);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### The Bug: Unexpected Rendering with Falsy Values
|
||||||
|
|
||||||
|
In this code snippet, if `showContent` happens to be a falsy value, such as `0`, the component will render an unexpected result. Instead of gracefully not rendering the content, it will display `0` on the screen due to the direct inclusion of curly braces.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
I gotcha gif
|
||||||
|
|
||||||
|
#### What's the Problem?
|
||||||
|
|
||||||
|
The issue lies in the mismanagement of truthy and falsy values. The direct use of curly braces creates an object wrapper (`[object Object]`), causing the component to render whatever value is present, even if it's falsy.
|
||||||
|
|
||||||
|
#### How to Solve it
|
||||||
|
|
||||||
|
To catch rendering bugs related to truthy and falsy values, use a more explicit conditional check.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const CorrectConditionalComponent = ({ showContent }) => (
|
||||||
|
showContent ? <div>Show me if true!</div> : null
|
||||||
|
);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
In this corrected version, the ternary operator ensures a clear check for truthiness, preventing unexpected rendering issues. By explicitly handling truthy and falsy values, you build robust components that behave predictably in various scenarios.
|
||||||
|
|
||||||
|
### Ignoring Dependency Arrays in React Hooks
|
||||||
|
|
||||||
|
Imagine working on a component that relies on an effect to perform some logic when a certain state, let's say `count`, changes. But even though you're incrementing the count, the effect doesn't seem to run, and you're left wondering why your logic isn't taking effect.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Counter = () => {
|
||||||
|
const [count, setCount] = useState(0);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
|
||||||
|
setCount((count) => count + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("The current count value is ", count);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>Count: {count}</p>
|
||||||
|
<button onClick={handleClick}>Increment</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Testing the count component without fixing the useEffect dependency array
|
||||||
|
|
||||||
|
#### What's the Problem?
|
||||||
|
|
||||||
|
The issue lies in neglecting the dependency array in your `useEffect`. When you omit the dependencies, React might not recognize that the effect is tied to a specific piece of state, leading to stale data and unexpected behavior.
|
||||||
|
|
||||||
|
#### How to Solve it
|
||||||
|
|
||||||
|
To get your effect back on track, include the relevant dependencies in the dependency array. It's like setting up triggers – you're telling React, "Hey, run this effect whenever these specific pieces of data change."
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("The current count value is ", count);
|
||||||
|
}, [count]);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Which now fires the `useEffect` hook:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Testing the count component after fixing the useEffect dependency array
|
||||||
|
|
||||||
|
### Neglecting Optional Chaining for API Data
|
||||||
|
|
||||||
|
You're working on a component that displays user data fetched from an API. Everything seems fine until you encounter an unexpected runtime error. The culprit? A missing optional chaining operator.
|
||||||
|
|
||||||
|
#### What's the Problem?
|
||||||
|
|
||||||
|
API responses can be unpredictable, and not all data structures match your expectations. Neglecting optional chaining, especially when accessing deeply nested properties (looking at you Strapi response data 👀) can lead to runtime errors if a property is undefined.
|
||||||
|
|
||||||
|
#### How to Solve it
|
||||||
|
|
||||||
|
==To safeguard your component from unexpected errors, incorporate optional chaining (==`==?.==`==) when accessing nested properties in API data.==
|
||||||
|
|
||||||
|
As an example, say you want to read a deeply nested property (label) from this data:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
const data = {
|
||||||
|
id: 1,
|
||||||
|
title: "First Item",
|
||||||
|
content: "Content for the first item",
|
||||||
|
category: {
|
||||||
|
id: 101,
|
||||||
|
name: "Category A",
|
||||||
|
description: "Description of Category A",
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
id: 1001,
|
||||||
|
label: "Tag 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1002,
|
||||||
|
label: "Tag 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
id: 201,
|
||||||
|
name: "John Doe",
|
||||||
|
email: "john.doe@example.com",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The correct way would be to use optional chaining to retrieve that data:
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
const firstLabel = data?.category?.tags?.[0]?.label;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Rather than accessing those properties directly:
|
||||||
|
|
||||||
|
```angelscript
|
||||||
|
const firstLabel = data.category.tags[0].label;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This prevents you from seeing a white screen error and a flooded console if the data structure changes. It's like putting on a safety net – if a property is missing, your app won't come crashing down like so:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Error occurring when optional chaining isn't applied
|
||||||
|
|
||||||
|
### Ignoring React Fragments for Grouping JSX Elements
|
||||||
|
|
||||||
|
When working with React components, you may encounter a scenario where you want to return multiple JSX elements from a function, only to be met with a syntax error.
|
||||||
|
|
||||||
|
#### What's the Problem?
|
||||||
|
|
||||||
|
This is due to a limitation in JavaScript, as it doesn't allow the return of adjacent elements without a common parent.
|
||||||
|
|
||||||
|
Consider the following problematic code:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function User() {
|
||||||
|
return <div> David Jaja</div>
|
||||||
|
<div>Twitter: https://twitter.com/JajaDavid8</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This code results in an error: “Adjacent JSX elements must be wrapped in an enclosing tag.”
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Error occurring when JSX returns 2 direct adjacent elements
|
||||||
|
|
||||||
|
#### How to Solve it
|
||||||
|
|
||||||
|
I know what you might be thinking—why not simply wrap the elements in a div and move on?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Spongebob bored gif
|
||||||
|
|
||||||
|
While this seems like a quick fix, it introduces a potential downside. By adding a div, you create an unnecessary parent element in the DOM.
|
||||||
|
|
||||||
|
This additional markup, though resolving the immediate error, can lead to unintended consequences, such as affecting styles or layout, and may not align with optimal coding practices.
|
||||||
|
|
||||||
|
And I’m sure you don’t want to end up with a "divpocalipse".
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A divpocalpse
|
||||||
|
|
||||||
|
To overcome both the syntax error and the unnecessary DOM markup, React introduced an optimized solution: React Fragments.
|
||||||
|
|
||||||
|
React Fragments are used to address the need for returning multiple JSX elements without introducing unnecessary parent elements in the DOM.
|
||||||
|
|
||||||
|
Here's how you can utilize React Fragments:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import React from "react";
|
||||||
|
function User() {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<div> David Jaja</div>
|
||||||
|
<div>Twitter: https://twitter.com/JajaDavid8</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using the shorthand syntax:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function User() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div> David Jaja</div>
|
||||||
|
<div>Twitter: https://twitter.com/JajaDavid8</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
By using React Fragments, you maintain clean and concise JSX code without introducing unnecessary elements to the DOM, enhancing code readability.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Showing the DOM tree after using fragments without any extra elements
|
||||||
|
|
||||||
|
## Opinionated Approaches to React
|
||||||
|
|
||||||
|
I've found some handy ways to make working with React more enjoyable. Instead of strict rules, think of these as my personal choices to make code easier to read, improve how it works, and make sure it stays in good shape.
|
||||||
|
|
||||||
|
1. **==Put data outside components==**==: Move things like lists and groups of information outside the main part of a component when possible. This helps avoid extra updates and makes it simpler to handle data without using special functions like== `==useCallback==`==.==
|
||||||
|
2. **==Be careful with== `==React====.====memo==`**==: Using== `==React====.====memo==` ==can help your components run better, but it's not always needed. If a component changes a lot with new information, using== `==React====.====memo==` ==might not be as helpful. Use it wisely.==
|
||||||
|
3. **==Create your own custom React hooks==**==: I also like making my own special tools with custom React hooks. It's a bit advanced, but it helps keep my code neat and organized.==
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Just my opinion gif
|
||||||
|
|
||||||
|
## Wrapping Up the Quirky Journey with React
|
||||||
|
|
||||||
|
React's journey is a blend of smooth sailing and bumpy rides. We've seen the strength of reusable components and virtual DOM and tackled puzzling moments like missing key props and conditional rendering bugs and so on.
|
||||||
|
|
||||||
|
As you continue your journey with React, may your code be clean, your components reusable, and your "What's Up with React?" moments turn into "Aha!" revelations. Happy coding! 🚀
|
||||||
|
|
||||||
|
### **Contact Information**
|
||||||
|
|
||||||
|
Want to connect or contact me? Feel free to hit me up on the following:
|
||||||
|
|
||||||
|
* Twitter: [@jajadavid8](https://twitter.com/JajaDavid8)
|
||||||
|
* LinkedIn: [David Jaja](https://www.linkedin.com/in/david-jaja-8084251b4/)
|
||||||
|
* Email: Jajadavidjid@gmail.com
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. [Get started](https://www.freecodecamp.org/learn/)
|
||||||
|
|
@ -71,3 +71,6 @@ Follow along using the transcript.
|
||||||
## Comments 1.7K
|
## Comments 1.7K
|
||||||
|
|
||||||
## Transcript
|
## Transcript
|
||||||
|
|
||||||
|
## Layouts
|
||||||
|
- [How to Properly Layout A Website (For Beginners)](https://www.youtube.com/watch?v=3C_22eBWpjg&t=604s)
|
||||||
9
templates/Intermediate Package.md
Normal file
9
templates/Intermediate Package.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
## Brainstorm
|
||||||
|
|
||||||
|
- Item
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- Item
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
|
@ -5,15 +5,6 @@ status: Backlog
|
||||||
---
|
---
|
||||||
# <% tp.file.folder() %> <% await tp.file.rename("README") %>
|
# <% tp.file.folder() %> <% await tp.file.rename("README") %>
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
```tasks
|
|
||||||
(path includes <% tp.file.folder(true) %>) AND (filename does not include {{query.file.filename}})
|
|
||||||
group by function task.file.pathWithoutExtension.split('/').slice(2).join("/")
|
|
||||||
sort by urgency
|
|
||||||
hide backlink
|
|
||||||
```
|
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- Item
|
- Item
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue