反应示例
一个反应组件库,用于方便的产品分析仪器.
项目状况
反应-标注不是官方支持的Ampliude SDK或库,现在已贬值.
请用我们的外观 脚本 SDK 跟踪 React !
传统、基于事件的必要伐木问题
- 背景事件信息(即"事件属性")往往需要大量管道通向事件被记录的代码路径,需要更多的代码并被解封.
- 同样,对于在低级,可再用组件(如按钮,滴出,链接等)中发射的事件,也很难提供背景信息.
- 传统的以事件为基础的分析记录经常使用必须的API,这有时可能要求更多的代码,在写出声明反应组件时会更痛苦.
“自动跟踪”解决方案的问题
- 自动跟踪解决方案可能不可靠,因为它们可能依赖于工程师可能无意中改变的属性(如CSS选择器).
- 自动跟踪解决方案可能无意中跟踪敏感的用户数据.
- 自动跟踪无法捕捉出各种事件,所以你可能会最终需要执行人工事件记录.
解决办法
反应-标注具有现代的,可声明的API,以方便与标注一起对新事件和属性进行仪器化. 它利用核心反应特性通过组件分级传播背景信息。 这使得在现有事件上添加出新的事件属性变得痛苦得多.
与“自动跟踪”解决方案不同, 反应比照需要 有点 代码更改,以便开始将数据发送到Amplitude。 然而,它旨在将开始收集数据所需的代码数量减少到最低程度,并使仪器的制作看起来不那么像一种花招.
如果您在您的 React 应用程序中使用了常见的可再使用组件,如按钮,滴放,链接等,那么您应该能够仅用几行代码实现"自动跟踪"式的仪器化. 从这里,可以非常简单地将新属性和上下文设置在你的应用中, 给予你与人工事件记录一样的灵活性.
示例: 设备化 Tic- Tac- Toe (来自 Facebook) 重现教程的入门(中文(简体) )
记录的事件 :
- 开始游戏
- 游戏赢了
- 单击正方形
- 跳转到移动
- 进入游戏开始
事件属性 :
- 范围(阵列;"平方","历史","游戏")
- 移动(数目)
- 赢家 ("X"或"O")
- 当前播放器 ("X"或"O")
import React from "react";
import { render } from "react-dom";
import amplitude from "amplitude-js";
import {
AmplitudeProvider,
Amplitude,
LogOnMount
} from "@amplitude/react-amplitude";
const AMPLITUDE_KEY = "";
function Square(props) {
return (
<Amplitude
eventProperties={inheritedProps => ({
...inheritedProps,
scope: [...inheritedProps.scope, "square"]
})}
>
{({ instrument }) => (
<button
className="square"
onClick={instrument("click square", props.onClick)}
>
{props.value}
</button>
)}
</Amplitude>
);
}
class Board extends React.Component {
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
history: [
{
squares: Array(9).fill(null)
}
],
stepNumber: 0,
xIsNext: true
};
}
handleClick(i) {
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? "X" : "O";
this.setState({
history: history.concat([
{
squares: squares
}
]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext
});
}
jumpTo(step) {
this.setState({
stepNumber: step,
xIsNext: step % 2 === 0
});
}
render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);
const moves = history.map((step, move) => {
const desc = move ? "Go to move #" + move : "Go to game start";
return (
<li key={move}>
<Amplitude
eventProperties={inheritedProps => ({
...inheritedProps,
scope: [...inheritedProps.scope, "move button"]
})}
>
{({ logEvent }) => (
<button
onClick={() => {
logEvent(move ? "jump to move" : "go to game start");
this.jumpTo(move);
}}
>
{desc}
</button>
)}
</Amplitude>
</li>
);
});
let status;
if (winner) {
status = "Winner: " + winner;
} else {
status = "Current player: " + (this.state.xIsNext ? "X" : "O");
}
return (
<AmplitudeProvider
amplitudeInstance={amplitude.getInstance()}
apiKey={AMPLITUDE_KEY}
>
<Amplitude
eventProperties={{
scope: ["game"],
"moves made": this.state.step,
"current player": this.state.xIsNext ? "X" : "O",
winner
}}
>
<LogOnMount eventType="start game" />
{!!winner && <LogOnMount eventType="game won" />}
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={i => this.handleClick(i)}
/>
</div>
<Amplitude
eventProperties={inheritedProps => ({
...inheritedProps,
scope: [...inheritedProps.scope, "history"]
})}
>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</Amplitude>
</div>
</Amplitude>
</AmplitudeProvider>
);
}
}
// ========================================
render(<Game />, document.getElementById("root"));
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
安装
以 npm 为单位 :
npm install --save @amplitude/react-amplitude
用纱线:
yarn add @amplitude/react-amplitude
反应-标本不会随自己的副本而来. Amplitude JavaScript SDK. 您可以通过 npm 或用 JavaScript 片段安装 Amplition SDK .
API 密码
显示道具
振幅强度
必需的道具 你应该提供一个振幅实例 从振幅 JS SDK的返回 getInstance 方法.
键
一种可选道具,可以用来以提供的密钥来初始化振幅实例.
用户编号
一种可选道具,可用于将所有事件归属于特定用户.
振幅道具
儿童
如果能够通过一个函数作为子道具,它将被调用单个对象参数,该函数的返回值将被用于渲染实际的React子树.
单对象参数有两个有用的字段: logEvent 财务报告和审定财务报表 instrument。 。 。 .
logEvent 用于绝对记录事件。 此组件的所有事件属性 eventProperties 道具和任何所继承的财产将列入这些活动.
示例
function Button(props) {
return (
<Amplitude>
{({ logEvent }) =>
<button
onClick={() => {
logEvent('button click');
props.onClick();
}}
>
{props.children}
</button>
}
</Amplitude>
)
}
instrument 是一个函数,可用于声明记录事件。 如果您已有事件处理器, 请用 instrument,而事件会在每次执行正常事件处理器时开火. instrument 将两个参数,事件类型和函数取给代理.
instrument 如果您想防止通过像纯组件这样的组件Update优化程序重新上线,也是有益的。 它会记住它的论点,并在重报时返回相同的函数实例. 因此,不建议使用 instrument 用于在每次渲染时变化的函数(即插入或“狭义”函数) render) (中文(简体) ).
示例
function Button(props) {
return (
<Amplitude>
{({ instrument }) =>
<button
onClick={instrument('button click', props.onClick)}
>
{props.children}
</button>
}
</Amplitude>
)
}
属性
如果提供了对象,则对象将合并到组件层次上更高的事件属性,并包含在该组件中记录的所有事件或其子树中的任何组件中.
如果提供了一个函数,它将被调用一个单一参数, inheritedProperties,其中包含来自 React 组件分层中更高组件的所有事件属性。 此函数的返回值将被用于此组件中的所有登录事件或子树中的其他组件.
解除间隔
如果提供,该组件记录的事件将按这一数额解禁,以毫秒计.
用户属性
一个可选对象如果提供,将触发当前用户"用户属性"的更新
月球道具日志
事件类型
当此组件挂起时, 它会记录一个带有此值的事件作为事件类型 .
属性
当组件挂起时, 这些属性将被应用到事件 .
实例Name
THE 高度实例来记录事件.
日志交换道具
价值
必需的道具,当改变时(通过浅显的等同比较进行查找),记录一个事件.
事件类型
当 value prop 更改, 它会记录一个带有此值的事件作为事件类型 .
属性
当组件挂起时, 这些属性将被应用到事件 .
实例Name
将事件记录到的振幅实例 .
许可证
麻省理工学院
朋友和相关项目
- 分析-反应:与分块一起写一次分析码,从任何来源收集客户数据并发送给超过250+目的地.