React Portals

了解如何使用 React Portals React 16 於 2017 年 9 月发布了 Portals。 Portal 是在組件層次結構之外的地方渲染元素的方法,它位於一個獨立的組件中。 當該元素被渲染時,它上發生的事件將由 React 組件層次結構管理,而不是由 DOM 位置所定義的層次結構管理。 因此有了 “portal” 這個名字:一個元素存在於 DOM 樹的某個位置,超出了普通的 React 組件樹,但包含它的 React 組件樹仍然負責管理它。 React 提供了一個簡單的 API 來實現這一點,即 ReactDOM.createPortal() ,它接受兩個參數。第一個是要渲染的元素,第二個是要渲染到的 DOM 元素。 這一功能的典型用例是模態窗口。 模態窗口要全屏渲染,必須存在於元素之外,以便可以使用 CSS 正確地應用樣式。 所以如果把模態窗口定義為一個組件: class Modal extends React.Component { constructor(props) { super(props) this.el = document.createElement('div') } componentDidMount() { document.getElementById('modal').appendChild(this.el) } componentWillUnmount() { document.getElementById('modal').removeChild(this.el) } render() { return ReactDOM.createPortal( this.props.children, this.el ) } } 我們可以在 App 組件中渲染它,並且即使技術上模態窗口是在不同的 DOM 樹中渲染的,也會由 App 組件處理模態窗口中發生的所有事件:...

React PropTypes

如何使用PropTypes設置prop的要求類型 由於JavaScript是一種動態類型的語言,我們實際上沒有辦法在編譯時強制變量的類型,如果我們傳遞無效類型,它們將在運行時失敗,或者如果類型是兼容的但不是我們期望的類型時,將會得到奇怪的結果。 Flow和TypeScript在這方面提供了很大的幫助,但React有一種直接幫助處理props類型的方法,即使在運行代碼之前,我們的工具(編輯器,linters)可以檢測到我們傳遞了錯誤的值: import PropTypes from 'prop-types' import React from 'react' class BlogPostExcerpt extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.description}</p> </div> ) } } BlogPostExcerpt.propTypes = { title: PropTypes.string, description: PropTypes.string } export default BlogPostExcerpt 哪些類型可以使用 這些是我們可以接受的基本類型: PropTypes.array PropTypes.bool PropTypes.func PropTypes.number PropTypes.object PropTypes.string PropTypes.symbol 我們可以接受兩種類型中的其中一種: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]), 我們可以接受多個值中的一個: PropTypes.oneOf(['Test1', 'Test2']), 我們可以接受一個類的實例: PropTypes.instanceOf(Something) 我們可以接受任何React節點: PropTypes.node 甚至可以接受任何類型: PropTypes.any 數組有一種特殊的語法,我們可以使用它來接受特定類型的數組: PropTypes.arrayOf(PropTypes.string) 對於對象,我們可以通過以下方式組合對象的屬性: PropTypes.shape({ color: PropTypes.string, fontSize: PropTypes.number }) 要求屬性 將isRequired添加到任何PropTypes選項中,如果該屬性缺失,React將返回一個錯誤:...

React 中如何使已勾選的複選框可編輯

在 React 中如何添加一個預設為已勾選狀態但仍然可以編輯的複選框 我在一個 React 組件中有一個複選框: <input name="enable" type="checkbox" /> 我希望它默認為已勾選狀態,但用戶仍然可以更改其值。 使用以下方式無法達到目標: <input name="enable" type="checkbox" checked="checked" /> 複選框的狀態無法被改變。 解決方法是使用 defaultChecked 屬性: <input name="enable" type="checkbox" defaultChecked={true} /> 如果複選框的狀態取決於某個變量的值(例如在編輯表單中,從數據庫中獲取實際值),則可以使用以下方式: <input name="enable" type="checkbox" defaultChecked={existing\_enable\_value} />

React 中的單向數據流

在使用 React 開發時,你可能會遇到「單向數據流(Unidirectional Data Flow)」這個概念。這究竟是什麼意思呢? 單向數據流並不是 React 獨有的概念,但作為 JavaScript 開發者,你可能第一次聽到這個名詞。 一般來說,這個概念指的是數據只有一種方式可以被傳遞到應用程序的其他部分。 在 React 中,這意味著: 狀態(state)被傳遞到視圖和子組件 动作(actions)由視圖觸發 動作可以更新狀態 視圖和子組件接收到狀態的更改 視圖是應用程序狀態的結果。狀態只有在動作發生時才能改變。當動作發生時,狀態會被更新。 由於單向綁定的特性,數據無法反向流動(例如使用雙向綁定時),這帶來了一些關鍵優勢: 較少的錯誤,因為你對數據有更多的控制權 更容易進行調試,因為你知道數據是從哪裡來的 更高效,因為庫已經知道每個系統部分的邊界是什麼 每個組件永遠只擁有一個狀態。受這個狀態影響的任何數據只能影響其下方的組件:即它的子組件。 改變組件的狀態永遠不會影響它的父組件、它的兄弟組件或應用程序中的其他組件- 只會影響它的子組件。 這就是為什麼狀態通常會在組件樹中往上移動,以便它可以在需要訪問它的組件之間進行共享。

React 事件

学习如何在React应用中与事件进行交互 React提供了一种简单的方式来管理事件。准备与addEventListener说再见吧。 在关于状态的上一篇文章中,你看到了这个例子: const CurrencySwitcher = props => { return ( <button onClick={props.handleChangeCurrency}> 当前货币是{props.currency}。更改它! </button> ) } 如果你已经使用JavaScript一段时间了,这就像是普通的JavaScript事件处理程序,只不过这次你是在JavaScript中定义一切,而不是在HTML中,并且你传递的是一个函数,而不是一个字符串。 实际的事件名称有一点不同,因为在React中你使用驼峰命名法,所以onclick变成了onClick,onsubmit变成了onSubmit。 作为参考,这是一个将JavaScript事件混合在一起的老派HTML: <button onclick="handleChangeCurrency()">...</button> 事件处理函数 在组件类中将事件处理函数定义为方法是一种惯例: class Converter extends React.Component { handleChangeCurrency = event => { this.setState({ currency: this.state.currency === '€' ? '$' : '€' }) } } 所有的处理函数都接收一个符合W3C UI Events规范的事件对象,可跨浏览器使用。 在方法中绑定this 不要忘记绑定方法。ES6类的方法默认情况下不绑定this。这意味着如果你不将方法定义为箭头函数,this将不会被定义: class Converter extends React.Component { handleClick = e => { /\* ... \*/ } //... } 使用Babel的属性初始化语法(在create-react-app中默认启用)时,或者需要在构造函数中手动绑定: class Converter extends React....

React 渲染屬性

學習如何使用渲染屬性來構建 React 應用程序 一個常見的模式用於在組件間共享狀態是使用 children 屬性。 在組件的 JSX 中,你可以渲染 {this.props.children} ,它會自動將父組件中傳遞的任何 JSX 插入為子元素: class Parent extends React.Component { constructor(props) { super(props) this.state = { /*...*/ } } render() { return <div>{this.props.children}</div> } } const Children1 = () => {} const Children2 = () => {} const App = () => ( <Parent> <Children1 /> <Children2 /> </Parent> ) 然而,這裡存在一個問題:無法從子元素中訪問父組件的狀態。 為了能夠共享狀態,你需要使用一個渲染屬性組件,而不是將組件作為父組件的子元素傳遞。你需要傳遞一個函數,在 {this.props.children()} 中執行該函數。該函數可以接受參數: class Parent extends React.Component { constructor(props) { super(props) this....

React 片段

如何使用 React 片段創建不可見的 HTML 標籤 請注意,我將返回值包裝在 div 中。這是因為組件只能返回一個元素,如果你想要多於一個元素,你需要用另一個容器標籤包裹它。 然而,這會在輸出中引入一個不必要的 div。你可以通過使用 React.Fragment 來避免這種情況: import React, { Component, Fragment } from 'react' class BlogPostExcerpt extends Component { render() { return ( <React.Fragment> <h1>{this.props.title}</h1> <p>{this.props.description}</p> </React.Fragment> ) } } 此外,還有一種非常簡潔的簡寫語法 <></>,它僅在最新版本(和 Babel 7+)中受到支持: import React, { Component, Fragment } from 'react' class BlogPostExcerpt extends Component { render() { return ( <> <h1>{this.props.title}</h1> <p>{this.props.description}</p> </> ) } }

React 狀態

如何與組件的狀態互動 設置默認狀態 在組件的構造函數中,初始化this.state。例如,BlogPostExcerpt 組件可能有一個clicked的狀態: class BlogPostExcerpt extends Component { constructor(props) { super(props) this.state = { clicked: false } } render() { return ( <div> <h1>標題</h1> <p>描述</p> </div> ) } } 訪問狀態 可以通過引用this.state.clicked來訪問 clicked 狀態: class BlogPostExcerpt extends Component { constructor(props) { super(props) this.state = { clicked: false } } render() { return ( <div> <h1>標題</h1> <p>描述</p> <p>點擊: {this.state.clicked}</p> </div> ) } } 改變狀態 永遠不要使用以下方式修改狀態: this.state.clicked = true 相反,應始終使用setState(),並將一個對象作為參數傳遞給它: this.setState({ clicked: true }) 該對象可以包含狀態的子集或超集。只有傳遞的屬性才會被修改,忽略的屬性將保持當前狀態。...

react-edit-doubleclick

#React,雙擊編輯文本 如何在React中雙擊元素時編輯頁面的某部分 我需要監聽元素的雙擊事件並使該元素可編輯。 一種方法是使用toggle狀態變量,當元素被雙擊時顯示不同的元素: const [toggle, setToggle] = useState(true) const [name, setName] = useState('test') ... toggle ? ( <p onDoubleClick={() => { setToggle(false) }} >{name}</p> ) : ( <input type='text' value={project.status} /> )} 然後,我們將一些屬性添加到input元素。首先,我們將name狀態分配給value屬性。 然後,我們使用onChange()事件監聽器來在input字段的內容發生變化時設置name變量的值。 最後,我們使用onKeyDown()來攔截Enter或Escape按鍵事件,並返回顯示p元素: <input type="text" value={name} onChange={(event) => { setName(name) }} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === 'Escape') { setToggle(true) event.preventDefault() event.stopPropagation() } }} /> 你也可以在該函數中添加任何副作用,例如在需要時將值保存到其他位置。

React,在元素新增至 DOM 時將焦點設定至項目

如何在 React 中在元素新增至 DOM 時設定焦點? 我有一個包含簡單表單的模態對話框,其中只有一個 input 欄位,我希望當模態對話框由 React 添加到 DOM 時,該元素能夠自動獲得焦點。 我開始思考許多不同的方式來實現這樣的效果,或許使用 useEffect() 來在組件添加到 DOM 時觸發事件,或者使用 ref 屬性來創建對 DOM 元素的引用並調用其 focus() 方法。不過後來我意識到我想得太複雜了,只需要在元素上使用 HTML 的 autofocus 屬性就可以解決這個問題。 果然如此。請記住,在 JSX 中它是 autoFocus,F 是大寫的: <input autoFocus ...// 其他輸入欄位的屬性