-
Notifications
You must be signed in to change notification settings - Fork 0
[2020-03-29]react-weather-app專案紀錄 #48
Description
學習紀錄:
- 在基於React庫的專案中,我們不會直接跟DOM打交道,而是跟React庫所具有的虛擬DOM進行交互。那麼直接透過
useEffect去針對html元素進行修改是good practice嗎?
useEffect(() => {
if(isSidebarOpen){
document.body.classList.add('hideScrollbar')
}
return () => {
document.body.classList.remove('hideScrollbar')
}
}, [isSidebarOpen])
於2020/03/30更新:
關於以上問題,基於在Discord上詢問的結果,我目前的理解是,的確直接以document取得元素並進而去進行修改是不建議的(會mutate the dom; it's therefore not advisable)。
但是在我所給出的例子中,因為body元素超出react所能handle的範圍,所以可以這樣做。
useEffect裡cleanup function的使用情境以及時機?- 使用axios拿取資料後,使用
.catch不就可以進行錯誤處理了,為何還要進行以下response.status === 200的確認?
function handleReponse(response) {
if (response.status === 200) {
return response
} else {
throw new Error('Error: Location ' + response.statusText)
}
}
- 透過API取為資料後,因為我們只需要一部份得資料,所以可以自建另一個function來mapping我們所需要的資料,同時去除我們不需要使用到的資料。
- 專案中所使用的Weather Icons,其官網上所說明的使用方式並沒有提到可以透過CDN使用,為何實際上卻可透過CDN引用,難道所有放在GitHub的repo實際上都可以透過CDN引用嗎?
- 可以透過
import語法將JSON檔案引讓JS檔案做使用,示例如下:
import * as weatherIcons from '../icons'
- 從OpenWeatherMap傳回來的data中,每筆天氣會帶有icon對應的id碼(Example),可以跟Weather Icons裡的相互搭配使用。網路上已有前輩整理好各icon的id對應到Weather Icons裡class的名稱了,請見以下網址:_usage.md。它實際上就是在說在返回data中啊,weather[0].id就等同於icons.json檔案裡的數字,而這數字(就拿下面的300來說好了)會對應Weather Icons裡sprinkle的icon,所以引用的辦法就是,以返回data的icon_id去取icons.json的icon的值("sprinkle"),取到的值加上"wi-"就會等同於Weather Icons裡的class名稱,就可以順利使用Weather Icons裡的Icons了!
weather": [
{
"id": 300,
"main": "Drizzle",
"description": "light intensity drizzle",
"icon": "09d"
}
],
*以上程式碼取自這裡。
"300": {
"label": "light intensity drizzle",
"icon": "sprinkle"
},
*以上程式碼取自這裡。
8. React component一定要返回something,如果針對return的東西設立條件(if(true))但沒有寫明不符條件時該怎麼處理,則React會報錯。
9. useRef的使用案例之我們想要知道某事件的發生是否在特定react component之外:
範例解說:
- 我們使用
useRef去保存我們欲被點擊的元素,在該元素上以ref此屬性就可以指定我們綁定的元素為何。 - 使用
useRef所保存的值在react每次render中都會保持不變。 - 之後,當事件發生時,我們檢查ref.current是否存在,若存在的話檢查ref是否存在任何子元素(包含本身元素)為event.target,若是的話,代表我們依舊點擊在元素內,而非元素外。
- 我突然發覺,我缺少一個重要認知,component之所以會是一個component,就是因為他們之間具有parent-child的關係。就比如說一個button component,那他的組成會是什麼?會是button element跟textNode,一個列表component,他的組成會是什麼?會是order list跟他的list Item,跟以降的所有其他child elements。所以,當今天我想要檢查我的事件是否發生在某個component之外時,我應該具備一個認知說,我要檢查此component所有組成的parent & child element是否包含這個事件,這也是為何在範例程式碼中會使用
containsmethod的原因。
import React, { useRef, useEffect } from "react";
/**
* Hook that alerts clicks outside of the passed ref
*/
function useOutsideAlerter(ref) {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
alert("You clicked outside of me!");
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
/**
* Component that alerts if you click outside of it
*/
export default function OutsideAlerter(props) {
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef);
return <div ref={wrapperRef}>{props.children}</div>;
}
*以上程式碼取自此StackOverflow的回答
10 .<a rel="noopener noreferrer”>屬性:為了解決跨域的安全問題,當使用target="_blank"打開一個新的標籤頁時,新頁面的window物件有一個屬性opener,其指向前一個頁面的window物件,換句話說,後一個新開的頁面會獲得對前一個頁面的控制權,如此可能會產生安全性方面的問題。為了解決問題,我們就需要使用在a tag上使用rel="noopener noreferrer”聲明我們不要opener!
11. csstransition的問題:在此專案上遇到一個transition使用上的問題。是這樣的,transition指定元素屬性在過度時的效果以及花費時間,而在此專案中,我在sidebar上使用了transition效果,指定sidebar從畫面滑進跟滑出時的效果以及所花費的時間。那照理來說,此滑進滑出所使用到的屬性僅是transform: translateX(400px)而已,所以在transition屬性上有特別指定transform為其屬性值,而非all。但問題來了,在sidebar從畫面滑進時,transition有發揮作用,可在sidebar滑出時,transition就失效了(所謂的失效指的是sidebar並非慢慢滑出,而是啪一下地從螢幕上消失),後來我是將all作為transition的屬性值才成功解決這問題。為什麼呢???
.sidebar {
position: absolute;
z-index: 99;
right: 0;
display: flex;
flex-direction: column;
height: 100%;
width: 400px;
padding: 1.5rem;
font-family: Montserrat;
line-height: 1.5;
background-color: white;
box-shadow: 0px 8px 10px -5px rgba(0,0,0,0.2), 0px 16px 24px 2px rgba(0,0,0,0.14), 0px 6px 30px 5px rgba(0,0,0,0.12);
transform: translateX(400px);
transition: all 600ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.sidebar.open{
transform: translateX(0px);
}
於2020/03/31更新:
我自己透過在元素上增加/移除class測試在此過程中transition的效果是否都有成功,答案是肯定的,請見此codepen。
然而,在此react專案卻並非如此,從此可推斷可能跟react有關係。根據此則回答,可能跟element上有設置position屬性,從而導致react在rerender時,transition無法成功發揮作用有關。