我有一个图表,但它没有使用 React Chart-js-2 更新图表

问题描述 投票:0回答:3

我有一个基于API的React天气项目 我有一个名为 CHART 的组件,但它没有更新项目最重要的部分。 每当我输入城市名称时,它都会获取所有信息并更新项目的书面部分。但它不是用图表来做的。它总是显示第一次调用的第一个值但不更新。 当我进入 Chart.js 文件并在项目中留出一个空间并点击“保存”时,它会显示基于 API 的正确图表。 我可以闻到一定有 useEffect Hook 的用例,但是如何?

这是子组件

import React, {  useEffect, useState } from 'react';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS} from 'chart.js/auto';

const Chart = ({following}) => {
  const date = following.map(item => new Date(item.dt * 1000));
  const dateLocal = date.map(item => item.toLocaleString('default', { weekday: 'long' }));
  const temp = following.map(item => Math.floor(item.temp.day));



  const [userData, setUserData] = useState({
    labels: dateLocal,
    datasets: [
      { 
        data: temp,    
        label: 'Temperature',
        backgroundColor: [
          'rgba(0, 0, 0,.5)',
          'rgba(0, 0, 0,.5)',
          'rgba(0, 0, 0,.5)',
        ],
        color : ['rgba(0,0,0,1)'],
        fill:true,  
        pointRadius: 1,
        pointHitRadius:4,
        pointHoverRadius:8,
        pointBackgroundColor: 'mediumblue',
        borderWidth: 2,
        pointBorderColor: 'lightblue',
        pointBorderWidth: 2,
        pointHoverBorderWidth: 2,
        tooltips: {
          mode: 'index',
          intersect: true,
          windowPadding: 10,
        },
        scales: {
          xAxes: [{
            gridLines: {
              display: false,
            },
            ticks: {
              fontColor: 'green',
              zeroLineColor: 'blue',
              callback : 
               function (value) {
                  return value
                }
            }
          }],
          yAxes: [{
            gridLines: {
              display: false,
            },
            ticks: {
              fontColor: 'black',
              fontSize: 112,
              fontStyle: 'bold',
              color: 'red',
              callback :
                function (value) {
                  return value
                }
            }
          }]
        }
      }
    ]
  });

  return (
    <div className="line" style={{ width:'100%'}}>
    <Line  
      data={userData} 
     />
    </div>
  )
};

export default Chart;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

这是父App.js

import React, { useEffect, useState } from 'react';
import Chart from './Chart';

const api = {
  key: `${process.env.REACT_APP_API_KEY}`,
  base: 'https://api.openweathermap.org/data/2.5/'
}

function App() {

  const [query, setQuery] = useState('');
  const [weather, setWeather] = useState({});
  const [location, setLocation] = useState({ lat: '', lon: '' });
  const [following, setFollowing] = useState([]);
  


  const search = async (e) => {
    if (e.key === 'Enter') {
      await fetch(`${api.base}weather?q=${query}&units=metric&appid=${api.key}&lang=tr`)
        .then(res => res.json())
        .then(result => {
          setWeather(result);
          setQuery('');
          setLocation(result.coord);
          console.log(result);
          searchFollowing();
        }
        )
    }
  }



  useEffect(() => {
    if (location.lat && location.lon) {
      searchFollowing();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [location])

  const searchFollowing = async () => {
    await fetch(`${api.base}onecall?lat=${location.lat}&lon=${location.lon}&units=metric&exclude=hourly,minutely&appid=${api.key}`)
      .then(res => res.json())
      .then(result2 => {
        const array = result2.daily.slice(1, 6);
        console.log(following);
        setFollowing(array);
        // following == array
      }
      )
  }



  const integer = (number) => {
    return Math.floor(Math.round(number));
  }
 

  const mapped = (following) => {
    following = [...following];
    return following.map((item, idx) => {
      const date = new Date(item.dt * 1000);
      const date1 = date.toLocaleString('default', { weekday: 'long' });
      const icon = item.weather[0].icon;
      const day = integer(item.temp.day);
      const night = integer(item.temp.night);
      return (
        <div key={idx} className="box">
          <h4>{date1}</h4>
          <img
            src={`http://openweathermap.org/img/wn/${icon}.png`}
            alt='weather'
            width={100}
            height={100}
          />
          <h4>Gündüz &nbsp; &nbsp; {day} °C</h4>
          <h4>Gece &nbsp; &nbsp; {night} °C</h4>
        </div>
      )
    })
  }

  const dateBuild = (d) => {
    let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
    let days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']

    let day = days[d.getDay()]
    let date = d.getDate()
    let month = months[d.getMonth()]
    let year = d.getFullYear()

    return `${day} ${date} ${month} ${year}`
  }


  return (
    <div className={(typeof weather.main !== 'undefined') ?
      ((weather.main.temp > 25) ? 'App hot' :
        ((weather.main.temp < 25 && weather.main.temp > 5) ?
          'App warm' : 'App')) : 'App'}>
      <main>
        <div className="search-box">
          <input
            type="text"
            className="search-bar"
            placeholder="Search for a location..."
            onChange={e => setQuery(e.target.value)}
            onKeyPress={search}
            value={query}
          />
        </div>
        {(typeof weather.main != "undefined") ? (
          <div className="content">
            <div className="location-box">
              <div className="location">
                {weather.name}, {weather.sys.country}
              </div>
              <div className="date"> {dateBuild(new Date())}
              </div>
            </div>
            <div className="weather-box">
              <div className="temp">
                {Math.round(weather.main.temp)}°C
                <img
                  src={`http://openweathermap.org/img/wn/${weather.weather[0].icon.slice(0, 2)}d.png`}
                  alt='weather'
                  width={150}
                  height={150}
                />
              </div>
              <div className="weather">
                <p>
                  <span>Hissedilen</span>
                  {Math.floor(weather.main.feels_like)} °C
                </p>
                <p>
                  <span>Şu an</span>
                  {weather.weather[0].description}
                </p>
                <p>
                  <span>Basınç</span>
                  {weather.main.pressure} mb
                </p>
                <p>
                  <span>Rüzgar </span>
                  {Math.floor(weather.wind.speed)} km/h
                </p>
                <p>
                  <span>En fazla</span>
                  {Math.floor(weather.main.temp_max)} °C
                </p>
                <p>
                  <span>En az</span>
                  {Math.floor(weather.main.temp_min)} °C
                </p>
              </div>
            </div>
            <Chart following={following} />
            <div className="followingdays"
            >
              {mapped(following)}
            </div>
          </div>) : ('')}
      </main>
    </div>
  );
}

export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

reactjs chart.js react-chartjs-2
3个回答
1
投票

UPDATE1 ==> 我用 useEffect 钩子完成了它,无法使用内置方法 update() 完成它

import React, {  useEffect, useState } from 'react';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS} from 'chart.js/auto';



const Chart = ({following}) => {
  const date = following.map(item => new Date(item.dt * 1000));
  const dateLocal = date.map(item => item.toLocaleString('default', { weekday: 'long' }));
  const temp = following.map(item => Math.floor(item.temp.day));

  // if userData changes then the chart will re-render
    useEffect(() => {
      setUserData({ 
        labels: dateLocal,
        datasets: [
          { 
            data: temp,       
            label: 'Temperature', 
            backgroundColor: [
              'rgba(0, 0, 0,.5)',
              'rgba(0, 0, 0,.5)',
              'rgba(0, 0, 0,.5)', 
            ],
            color : ['rgba(0,0,0,1)'],
            fill:true,  
            pointRadius: 1,
            pointHitRadius:4,
            pointHoverRadius:8,  
            pointBackgroundColor: 'mediumblue',
            borderWidth: 2,
            pointBorderColor: 'lightblue',
            pointBorderWidth: 2,
            pointHoverBorderWidth: 2, 
            tooltips: {
              mode: 'index',
              intersect: true,
              windowPadding: 10,
            },
            scales: {
              xAxes: [{
                gridLines: {
                  display: false,
                },
                ticks: {
                  fontColor: 'green'
                }
              }],
              yAxes: [{
                gridLines: {
                  display: false,
                }, 
                ticks: { 
                  fontColor: 'green' 
                }
              }] 
            }
          } 
        ]   
      });
    },[following]);


 
  const [userData, setUserData] = useState({ 
    labels: dateLocal,
    datasets: [ 
      { 
        data: temp,       
        label: 'Temperature', 
        backgroundColor: [ 
          'rgba(0, 0, 0,.5)',
          'rgba(0, 0, 0,.5)',
          'rgba(0, 0, 0,.5)',   
        ],
        color : ['rgba(0,0,0,1)'], 
        fill:true,  
        pointRadius: 1,
        pointHitRadius:4,
        pointHoverRadius:8,  
        pointBackgroundColor: 'mediumblue',
        borderWidth: 2,
        pointBorderColor: 'lightblue', 
        pointBorderWidth: 2,
        pointHoverBorderWidth: 2, 
        tooltips: {
          mode: 'index',
          intersect: true,
          windowPadding: 10,
        },
        scales: {
          xAxes: [{
            gridLines: {
              display: false,
            },
            ticks: {
              fontColor: 'green'
            }
          }],
          yAxes: [{
            gridLines: { 
              display: false,
            }, 
            ticks: { 
              fontColor: 'green' 
            }
          }] 
        } 
      } 
    ]     
  });

  return (
    <div className="line" style={{ width:'100%'}}>
    <Line className="actual-chart"
      data={userData}
      redraw={true}
     />    
    </div>
  ) 
}; 
  
export default Chart;
   
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


0
投票

Chart.js 有 update 方法。尝试将图表保存在变量中,然后在必要时调用 foo.update()


0
投票

我通过添加随机数作为图表元素的键来修复我的问题。示例;

<div>
<Line  
  key={Math.random()}
  data={userData} 
 />
</div>
© www.soinside.com 2019 - 2024. All rights reserved.