Rechart Tooltip无法正确渲染数据 求助解决
Recharts LineChart Tooltip 渲染异常,如何修改为仅显示对应数值的“X min”格式?
问题描述
使用Rechart的LineChart组件时遇到Tooltip渲染异常:当前Tooltip横向显示“SessionLength: 0min”(所有日期均如此),纵向显示鼠标指向日期的字母标识,期望Tooltip仅显示“X min”,其中X为该日期对应的sessionLength数值。
相关代码片段
1. data.js 相关部分
const USER_AVERAGE_SESSIONS = [ { userId: 12, sessions: [ { day: 1, sessionLength: 30 }, { day: 2, sessionLength: 23 }, { day: 3, sessionLength: 45 }, { day: 4, sessionLength: 50 }, { day: 5, sessionLength: 0 }, { day: 6, sessionLength: 0 }, { day: 7, sessionLength: 60 } ] }, { userId: 18, sessions: [ { day: 1, sessionLength: 30 }, { day: 2, sessionLength: 40 }, { day: 3, sessionLength: 50 }, { day: 4, sessionLength: 30 }, { day: 5, sessionLength: 30 }, { day: 6, sessionLength: 50 }, { day: 7, sessionLength: 50 } ] } ]
2. SessionLengthChart 组件代码
import React, { useState, useEffect } from "react"; import PropTypes from "prop-types"; import { getUserAverageSessions } from "../../../dataManager/dataManager"; import { useParams } from "react-router-dom"; import { LineChart, XAxis, YAxis, Tooltip, Line, CartesianGrid, } from "recharts"; import "./SessionLengthChart.css"; /** * SessionLengthChart component displays a line chart of a user's average session length per day. * @returns {JSX.Element} */ function SessionLengthChart() { // Define PropTypes for the component SessionLengthChart.propTypes = { userId: PropTypes.string.isRequired, }; // Extract userId from the URL using useParams const { userId } = useParams(); // Initialize state variables for user sessions and error const [userSessions, setUserSessions] = useState(null); const [error, setError] = useState(false); // Fetch user average session data when the component mounts or when userId changes useEffect(() => { /** * Fetches user average session data and updates the state. * @async */ async function fetchData() { try { // Get user average session data from the data manager const userData = await getUserAverageSessions(userId); // Update the userSessions state with the fetched data const updatedData = userData[1].map((dayData) => { const sessionLengthStr = dayData.sessionLength.toString(); const sessionLengthNum = Number(sessionLengthStr.match(/\d+/)[0]); const daysOfWeek = ["", "L", "M", "M", "J", "V", "S", "D"]; const day = daysOfWeek[dayData.day]; return { ...dayData, day: day, sessionLength: sessionLengthNum, }; }); setUserSessions(updatedData); } catch (err) { console.log("Error fetching user data:", err); setError(true); } } fetchData(); }, [userId]); // Display an error message if the data failed to load if (error) { return ( <div>Error: Failed to load user data for session length chart.</div> ); } // Display a loading message if user session data is not yet loaded if (!userSessions) { return <div>Loading...</div>; } // Format the label for X and Y axes of the chart const formatLabel = (value) => { if (value === 0) { return "0 min"; } const hours = Math.floor(value / 60); const minutes = value % 60; return `${hours > 0 ? `${hours}h ` : ""}${minutes}min`; }; // Format the tooltip for the chart const formatTooltip = (value) => { const hours = Math.floor(value / 60); const minutes = value % 60; return `${hours > 0 ? `${hours}h ` : ""}${minutes}min`; }; // Render the line chart with the user session data return ( <div className="Session"> <h3 className="sessionTitle">Durée moyenne des <br></br>sessions</h3> <LineChart width={268} height={263} data={userSessions} cursor="default" margin={{ top: 20, right: 10, left: 10, bottom: 30 }} > <XAxis dataKey="day" tick={{ stroke: "white", strokeWidth: 0.4, fontSize: 12 }} style={{ textAnchor: "middle", transform: "translateY(-0px) " }} /> <YAxis type="number" domain={[0, "dataMax"]} tickCount={5} width={0} stroke="transparent" axisline={false} /> <Tooltip formatter={(value) => { console.log(value); const sessionLength = value && value.payload ? value.payload.sessionLength : 0; return `${sessionLength} min`; }} contentStyle={{ width: 50, height: 30 }} label={null} isAnimationActive={false} /> <CartesianGrid stroke="#f5f5f5" vertical={false} /> <CartesianGrid stroke="#f5f5f5" horizontal={false} /> <Line type="monotone" data={userSessions} stroke="#fff" yAxis={null} dot={false} strokeWidth={2} dataKey="sessionLength" /> {console.log(userSessions, "achemene")} </LineChart> </div> ); } export default SessionLengthChart;
3. dataManager.js 相关部分
/** * Fetches user average sessions data from the server or mocked data. * @async * @returns {Array} - The user average sessions data. */ async function getUserAverageSessions(id) { const rawUserData = useMockedData ? await getMockedData("USER_AVERAGE_SESSIONS", id) : await importFromBackEnd("average-sessions", id); const userData = Object.values(rawUserData); // Transform the object into an array return userData; } export { getUserAverageSessions };
解决方案
问题出在Tooltip的formatter函数参数处理错误:Recharts中单个数据系列的formatter第一个参数直接对应dataKey的值(即sessionLength的数值),而非包含payload的对象,你之前的写法导致sessionLength始终取到默认值0。
修改Tooltip部分的代码即可解决:
基础版(仅显示“X min”)
<Tooltip formatter={(value) => [`${value} min`]} contentStyle={{ width: 50, height: 30 }} label={null} isAnimationActive={false} />
进阶版(支持小时+分钟格式,复用你定义的formatTooltip函数)
<Tooltip formatter={(value) => [formatTooltip(value)]} contentStyle={{ width: 50, height: 30 }} label={null} isAnimationActive={false} />
说明
formatter需要返回数组,每个元素对应一个数据系列的显示内容,这里只有一个Line系列,所以返回包含单个字符串的数组。label={null}用于隐藏Tooltip顶部的日期标识,符合你的需求。- 修正后,Tooltip会正确显示当前鼠标指向日期对应的
sessionLength数值格式,不再出现固定的0min和多余的键名。
内容的提问来源于stack exchange,提问作者Simon Flambeaux
相关产品推荐
相关产品推荐

