- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立一個事件感知元件
- ReactJS - 在 Expense Manager 應用中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 進行元件生命週期管理
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - Context
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - Fragments
- ReactJS - 高階元件
- ReactJS - 與其他庫整合
- ReactJS - 效能最佳化
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - 調和
- ReactJS - Refs 和 DOM
- ReactJS - Render Props
- ReactJS - 靜態型別檢查
- ReactJS - Strict Mode
- ReactJS - Web Components
- 其他概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 走馬燈
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - getSnapshotBeforeUpdate() 方法
眾所周知,在 React 中,每個元件都有其自身的生命週期,這意味著它們在專案中執行時會經歷不同的階段。React 提供了內建方法來控制這些過程。
現在讓我們看看 getSnapshotBeforeUpdate() 方法。假設我們正在使用 React 建立一個網頁和一個定期接收訊息的聊天元件。現在,我們不希望每次收到新訊息時滾動位置都發生變化,從而導致使用者丟失他們在對話中的位置。這就是 getSnapshotBeforeUpdate() 發揮作用的地方。
簡單來說,React 會在修改網頁之前不久呼叫此函式。它允許我們的元件從頁面中捕獲一些資訊,例如使用者滾動到的位置,然後再進行任何潛在的更改。
語法
getSnapshotBeforeUpdate(prevProps, prevState)
引數
prevProps − 這些是在更改之前存在的屬性。可以將它們與 this.props 進行比較,以檢視有什麼新內容。
prevState − 這是更改之前的先前狀態。要確定更改,請將其與 this.state 進行比較。
返回值
我們應該返回任何型別的快照值或 null。我們返回的值將作為第三個引數傳送給 componentDidUpdate。
示例
示例 1
讓我們構建一個使用 getSnapshotBeforeUpdate 函式的小型 React 應用。在這個示例中,我們將構建一個簡單的聊天應用程式,其中會收到新訊息,並且我們希望儲存滾動位置。
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
messages: [
{ id: 1, text: 'Hello!' },
{ id: 2, text: 'How are you?' },
],
newMessage: '',
};
this.chatWindowRef = React.createRef();
}
handleInputChange = (event) => {
this.setState({ newMessage: event.target.value });
};
handleSendMessage = () => {
const { messages, newMessage } = this.state;
// Create a new message object
const newMessageObj = {
id: messages.length + 1,
text: newMessage,
};
// Update the state with the new message
this.setState({
messages: [...messages, newMessageObj],
newMessage: '',
});
};
getSnapshotBeforeUpdate(prevProps, prevState) {
// Check if new messages are being added
if (prevState.messages.length < this.state.messages.length) {
const chatWindow = this.chatWindowRef.current;
return chatWindow.scrollHeight - chatWindow.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If there's a snapshot, adjust the scroll position
if (snapshot !== null) {
const chatWindow = this.chatWindowRef.current;
chatWindow.scrollTop = chatWindow.scrollHeight - snapshot;
}
}
render() {
const { messages, newMessage } = this.state;
return (
<div>
<div
ref={this.chatWindowRef}
style={{ height: '200px', overflowY: 'scroll', border: '1px solid #ccc', padding: '10px' }}
>
{/* Display messages */}
{messages.map((message) => (
<div key={message.id}>{message.text}</div>
))}
</div>
{/* Input for new message */}
<div>
<input type="text" value={newMessage} onChange={this.handleInputChange} />
<button onClick={this.handleSendMessage}>Send Message</button>
</div>
</div>
);
}
}
export default App;
輸出
在這個應用中:
ChatApp 元件保留訊息列表和用於新增新訊息的表單。
getSnapshotBeforeUpdate 函式用於找出是否正在新增新訊息以及記錄當前滾動位置。
如果添加了新訊息,componentDidUpdate 將更新滾動位置。
聊天視窗包含一個用於顯示訊息的可滾動區域。
示例 2
讓我們建立一個簡單的 React 應用,使用者可以在其中輸入數字並執行基本的算術運算。以下是程式碼:
import React, { Component } from 'react';
import './App.css';
class CalculatorApp extends Component {
constructor(props) {
super(props);
this.state = {
result: 0,
num1: '',
num2: '',
operator: '+',
};
}
handleNumChange = (event, numType) => {
const value = event.target.value;
this.setState({
[numType]: value,
});
};
handleOperatorChange = (event) => {
this.setState({
operator: event.target.value,
});
};
handleCalculate = () => {
const { num1, num2, operator } = this.state;
// Convert input values to numbers
const number1 = parseFloat(num1);
const number2 = parseFloat(num2);
// Perform calculation based on the selected operator
let result = 0;
switch (operator) {
case '+':
result = number1 + number2;
break;
case '-':
result = number1 - number2;
break;
case '*':
result = number1 * number2;
break;
case '/':
result = number1 / number2;
break;
default:
break;
}
// Update the state with result
this.setState({
result,
});
};
render() {
const { result, num1, num2, operator } = this.state;
return (
<div className='App'>
<div>
<input type="number" value={num1} onChange={(e) => this.handleNumChange(e, 'num1')} />
<select value={operator} onChange={this.handleOperatorChange}>
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="number" value={num2} onChange={(e) => this.handleNumChange(e, 'num2')} />
<button onClick={this.handleCalculate}>Calculate</button>
</div>
<div>
<strong>Result:</strong> {result}
</div>
</div>
);
}
}
export default CalculatorApp;
輸出
在此程式碼中,我們建立了一個簡單的計算器應用程式,使用者可以在其中輸入兩個數字,選擇一個算術運算子,然後單擊“計算”按鈕後檢視結果。
示例 3
讓我們建立一個小型 React 應用,允許使用者輸入任務並將它們標記為已完成。當新增新任務時,我們將使用 getSnapshotBeforeUpdate 函式滾動到任務列表的底部。以下是應用程式的程式碼:
import React, { Component } from 'react';
class TaskListApp extends Component {
constructor(props) {
super(props);
this.state = {
tasks: [],
newTask: '',
};
this.taskListRef = React.createRef();
}
handleInputChange = (event) => {
this.setState({ newTask: event.target.value });
};
handleAddTask = () => {
const { tasks, newTask } = this.state;
// Create a new task object
const newTaskObj = {
id: tasks.length + 1,
text: newTask,
completed: false,
};
// Update the state with the new task
this.setState({
tasks: [...tasks, newTaskObj],
newTask: '',
});
};
getSnapshotBeforeUpdate(prevProps, prevState) {
// Check if new tasks are being added
if (prevState.tasks.length < this.state.tasks.length) {
const taskList = this.taskListRef.current;
return taskList.scrollHeight - taskList.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
const taskList = this.taskListRef.current;
taskList.scrollTop = taskList.scrollHeight - snapshot;
}
}
handleToggleComplete = (taskId) => {
const updatedTasks = this.state.tasks.map((task) =>
task.id === taskId ? { ...task, completed: !task.completed } : task
);
this.setState({
tasks: updatedTasks,
});
};
render() {
const { tasks, newTask } = this.state;
return (
<div>
<div
ref={this.taskListRef}
style={{ height: '200px', overflowY: 'scroll', border: '1px solid #ccc', padding: '10px' }}
>
{/* Display tasks */}
{tasks.map((task) => (
<div key={task.id} style={{ textDecoration: task.completed ? 'line-through' : 'none' }}>
<input
type="checkbox"
checked={task.completed}
onChange={() => this.handleToggleComplete(task.id)}
/>
{task.text}
</div>
))}
</div>
{/* Input for new task */}
<div>
<input type="text" value={newTask} onChange={this.handleInputChange} />
<button onClick={this.handleAddTask}>Add Task</button>
</div>
</div>
);
}
}
export default TaskListApp;
輸出
在這個應用中,使用者可以輸入任務,將它們標記為已完成,並在列表中檢視任務。當新增新任務時,getSnapshotBeforeUpdate 函式用於滾動到任務列表的底部。
註釋
如果定義了 shouldComponentUpdate 並返回 false,則 React 將不會呼叫 getSnapshotBeforeUpdate。
目前,函式元件沒有 getSnapshotBeforeUpdate 的直接等效項。如果我們需要此功能,則必須使用類元件。
總結
我們已經看到了 getSnapshotBeforeUpdate() 函式的工作機制。我們還建立了一個小型應用程式來展示該函式的用法。此元件可以包含在我們的 React 應用程式中,以顯示 getSnapshotBeforeUpdate 如何在新增新內容時保持滾動位置。