React Router:如何從動態路由中獲取數據

當您使用 React Router 以動態參數的方式時,一個非常常見的需求是獲取我們在頁面中顯示的數據。 舉個例子,假設我們有一個項目列表,點擊項目後會進入項目詳情頁,URL 地址為 /project/PROJECT_ID。 我找到了兩種方法來實現這個需求。 首先,在路由中聲明這樣的路徑: <Route path="/project/:id"> <SingleProject /> </Route> 注意這裡的 /project/:id 路徑。這表示該組件將接收到 id 參數中的動態部分。 接下來,在 SingleProject 組件中,我們可以使用 useParams 鉤子來獲取 id 參數: import { useHistory, useParams } from 'react-router-dom'; //... const { id } = useParams(); 在我的案例中,我使用這個 id 參數從一個項目數組中過濾出數據,但您也可以使用它來查詢數據庫或者進行其他任務。 另一種方式是使用 props: <Route path="/project/:id" render={(props) => <SingleProject {...props} />} /> 在 SingleProject 組件中(即在上面的 render 屬性中列舉的那個組件),我們使用傳入的 props: function SingleProject(props) { //... } 這些 props 包含在 match.params 屬性下的參數,所以我們可以使用對象解構來重新獲取我們的 id:...

React Router:為什麼 useLocation 和 useHistory 可能會返回 undefined

我在使用 React Router 時,使用了 useLocation 和 useHistory hooks 的地方卻都返回了 undefined。這真是讓我感到困惑。 const history = useHistory() const location = useLocation() 結果都返回了 undefined。 後來才發現,我在同一個組件中使用 useLocation 和 useHistory 並在 DOM 中添加 <Router>...</Router>。 然後我找到了這個 issue,解釋說我不能這樣做。 我需要將 <Router>...</Router> 的包裹組件提升一層。在我的情況下,我在 index.js 文件中進行了如下修改: import { BrowserRouter as Router } from 'react-router-dom' ... ReactDOM.render( <React.StrictMode> <Router> <App /> </Router> </React.StrictMode>, document.getElementById('root') )

React Router介紹

React Router是連接URL和React應用程序的理想工具。React Router是事實上的React路由庫,也是React項目中最受歡迎的項目之一。 安裝 組件 BrowserRouter Link Route 在渲染的組件內訪問位置數據 以編程方式更改路由 匹配多個路徑 內聯渲染 匹配動態路由參數 React Router是事實上的React路由庫,也是React項目中最受歡迎的項目之一。 React本身是一個非常簡單的庫,對路由方面並沒有任何的規範。 在單頁應用程序中,路由是引入一些特性以通過鏈接導航應用程序的方式,這是正常Web應用程序中預期的: 在切換到不同屏幕時,瀏覽器應更改URL。 深度鏈接應該正常工作:如果將瀏覽器指向URL,應用程序應該重建生成該URL時呈現的相同視圖。 瀏覽器的返回(和前進)按鈕應該按預期工作。 路由將應用程序的導航與瀏覽器提供的導航功能連接在一起:地址欄和導航按鈕。 React Router提供了一種編寫代碼的方式,這樣只有在路由與您定義的內容匹配時才會顯示應用程序的特定組件。 安裝 使用npm安裝: npm install react-router-dom 組件 在使用React Router時,您最常互動的組件有: BrowserRouter,通常別名為Router Link Route BrowserRouter包裝了所有的Route組件。 Link組件用於生成指向您的路由的鏈接。 Route組件負責顯示或隱藏它們包含的組件。 BrowserRouter 下面是BrowserRouter組件的一個簡單示例。您從react-router-dom中導入它,並使用它來包裝您的整個應用程序: import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter as Router } from 'react-router-dom' ReactDOM.render( <Router> <div>{/* ... */}</div> </Router>, document.getElementById('app') ) BrowserRouter組件只能有一個子元素,所以我們將要添加的所有內容都包裝在一個div元素中。 Link Link組件用於觸發新的路由。您從react-router-dom中導入它,並可以添加Link組件以指向不同的路由,使用to屬性: import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter as Router, Link } from 'react-router-dom' ReactDOM....

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 片段創建不可見的 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 事件

学习如何在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 狀態

如何與組件的狀態互動 設置默認狀態 在組件的構造函數中,初始化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 渲染屬性

學習如何使用渲染屬性來構建 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 屬性(Props)

如何使用 props 在 React 元件之間傳遞資料 Props 是元件獲取屬性的方式。從最上層的元件開始,每個子元件都從父元件獲取它們的 props。在函數元件中,props 會作為函數參數傳遞,只能通過 props 來獲取: const BlogPostExcerpt = props => { return ( <div> <h1>{props.title}</h1> <p>{props.description}</p> </div> ) } 在類別元件中,props 會默認傳遞。不需要添加任何特殊代碼,可以在元件實例中使用 this.props 獲取 props: import React, { Component } from 'react' class BlogPostExcerpt extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.description}</p> </div> ) } } 將 props 傳遞給子元件是在應用程式中傳遞值的好方法。元件可以擁有資料(即具有狀態)或通過其 props 接收資料。 當出現以下情況時,會變得複雜: 需要從多級子元件中的子元件存取元件的狀態(即使前面的子元件不需要知道狀態,也需要它們作為中介)。 需要從完全無關的元件存取元件的狀態。 Props 的預設值 如果某些值不是必需的,則在元件初始化時需要為它指定一個預設值。 BlogPostExcerpt.propTypes = { title: PropTypes.string, description: PropTypes....