From a87a0fb61ad2a2860b79c2a59baf8e6598d6bbec Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Thu, 21 Oct 2021 13:08:49 -1000 Subject: [PATCH 1/4] Fix all optional chains --- STYLE.md | 17 ++++++++++++ src/components/AddressSearch.js | 6 ++++- src/libs/Network.js | 2 +- src/libs/actions/IOU.js | 6 +++-- src/libs/fileDownload/index.js | 2 +- src/libs/fileDownload/index.native.js | 26 ++++++++++--------- src/pages/NewChatPage.js | 3 ++- src/pages/RequestCallPage.js | 2 +- .../getSkinToneEmojiFromIndex.js | 6 ++--- src/pages/iou/IOUModal.js | 4 +-- .../IOUParticipantsSplit.js | 3 ++- src/pages/settings/PreferencesPage.js | 3 ++- src/pages/settings/Profile/ProfilePage.js | 5 ++-- 13 files changed, 57 insertions(+), 28 deletions(-) diff --git a/STYLE.md b/STYLE.md index 4017c5bff9fb..e584e4f45ded 100644 --- a/STYLE.md +++ b/STYLE.md @@ -175,6 +175,23 @@ Empty functions (noop) should be declare as arrow functions with no whitespace i } ``` +## Accessing Object Properties and Default Values + +Use `lodashGet()` to safely access object properties and `||` to short circuit null or undefined values that are not guaranteed to exist in a consistent way throughout the codebase. + + ```javascript + // Bad + const value = somePossiblyNullThing ?? 'default'; + // Good + const value = somePossiblyNullThing || 'default'; + // Bad + const value = someObject.possiblyUndefinedProperty?.nestedProperty || 'default'; + // Bad + const value = (someObject && someObject.possiblyUndefinedProperty && someObject.possiblyUndefinedProperty.nestedProperty) || 'default'; + // Good + const value = lodashGet(someObject, 'possiblyUndefinedProperty.nestedProperty', 'default'); + ``` + ## JSDocs - Avoid docs that don't add any additional information. - Always document parameters and return values. diff --git a/src/components/AddressSearch.js b/src/components/AddressSearch.js index 4f4dc581a886..6de28f19de4a 100644 --- a/src/components/AddressSearch.js +++ b/src/components/AddressSearch.js @@ -36,7 +36,11 @@ const defaultProps = { const AddressSearch = (props) => { const googlePlacesRef = useRef(); useEffect(() => { - googlePlacesRef.current?.setAddressText(props.value); + if (!googlePlacesRef.current) { + return; + } + + googlePlacesRef.current.setAddressText(props.value); }, []); // eslint-disable-next-line diff --git a/src/libs/Network.js b/src/libs/Network.js index a781595089c6..01592b51f381 100644 --- a/src/libs/Network.js +++ b/src/libs/Network.js @@ -189,7 +189,7 @@ function processNetworkRequestQueue() { } const requestData = queuedRequest.data; - const requestEmail = requestData.email ?? ''; + const requestEmail = lodashGet(requestData, 'email', ''); // If we haven't passed an email in the request data, set it to the current user's email if (email && _.isEmpty(requestEmail)) { diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index b64e348c7122..29e8b68227c6 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -85,7 +85,8 @@ function createIOUTransaction(params) { .then((data) => { getIOUReportsForNewTransaction([data]); Navigation.navigate(ROUTES.getReportRoute(data.chatReportID)); - })?.catch((error) => { + }) + .catch((error) => { Onyx.merge(ONYXKEYS.IOU, { loading: false, creatingIOUTransaction: false, @@ -134,7 +135,8 @@ function createIOUSplit(params) { } getIOUReportsForNewTransaction(reportParams); Navigation.navigate(ROUTES.getReportRoute(chatReportID)); - })?.catch((error) => { + }) + .catch((error) => { Onyx.merge(ONYXKEYS.IOU, { loading: false, creatingIOUTransaction: false, diff --git a/src/libs/fileDownload/index.js b/src/libs/fileDownload/index.js index aaddeee433ed..dea9353140a2 100644 --- a/src/libs/fileDownload/index.js +++ b/src/libs/fileDownload/index.js @@ -23,7 +23,7 @@ export default function fileDownload(url, fileName) { link.style.display = 'none'; link.setAttribute( 'download', - fileName ?? getAttachmentName(url), // generating the file name + fileName || getAttachmentName(url), // generating the file name ); // Append to html link element page diff --git a/src/libs/fileDownload/index.native.js b/src/libs/fileDownload/index.native.js index 064738142414..60c6dfd66234 100644 --- a/src/libs/fileDownload/index.native.js +++ b/src/libs/fileDownload/index.native.js @@ -60,7 +60,7 @@ function handleDownload(url, fileName) { // android files will download to Download directory // ios files will download to documents directory const path = getPlatform() === 'android' ? dirs.DownloadDir : dirs.DocumentDir; - const attachmentName = fileName ?? getAttachmentName(url); + const attachmentName = fileName || getAttachmentName(url); // fetching the attachment const fetchedAttachment = RNFetchBlob.config({ @@ -75,18 +75,20 @@ function handleDownload(url, fileName) { // resolving the fetched attachment fetchedAttachment.then((attachment) => { - if (attachment?.info()) { - showAlert({ - title: 'Downloaded!', - message: 'Attachment successfully downloaded', - options: [ - { - text: 'OK', - style: 'cancel', - }, - ], - }); + if (!attachment || !attachment.info()) { + return; } + + showAlert({ + title: 'Downloaded!', + message: 'Attachment successfully downloaded', + options: [ + { + text: 'OK', + style: 'cancel', + }, + ], + }); }).catch(() => { showAlert({ title: 'Attachment Error', diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 6aaa468b2671..57fa0767adcd 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -1,3 +1,4 @@ +import lodashGet from 'lodash/get'; import _ from 'underscore'; import React, {Component} from 'react'; import {View} from 'react-native'; @@ -258,7 +259,7 @@ class NewChatPage extends Component { forceTextUnreadStyle /> {!this.props.isGroupChat && } - {this.props.isGroupChat && this.state.selectedOptions?.length > 0 && ( + {this.props.isGroupChat && lodashGet(this.state, 'selectedOptions', []).length > 0 && (