Javascript React Redux更新状态,但不重新渲染,并且在render()中未定义props{}

Javascript React Redux更新状态,但不重新渲染,并且在render()中未定义props{},javascript,reactjs,redux,react-redux,react-props,Javascript,Reactjs,Redux,React Redux,React Props,所以我试图在react redux商店中设置一个计时器。我的操作被发送到减速器,如果我从减速器中输入console.log,我可以在控制台中看到它 我甚至在启动时间和停止计时器的按钮工作的地方连接了这些道具,因为我在控制台中每秒都会看到“滴答”的动作。然而,目前我最大的困惑是,即使我把它连接到商店上,我似乎看不到组件中呈现的值this.props在componentDidMount and render(){}上未定义。但是,同一组件上的按钮不会触发startTimer操作,因此它正在更新状态,

所以我试图在react redux商店中设置一个计时器。我的操作被发送到减速器,如果我从减速器中输入console.log,我可以在控制台中看到它

我甚至在启动时间和停止计时器的按钮工作的地方连接了这些道具,因为我在控制台中每秒都会看到“滴答”的动作。然而,目前我最大的困惑是,即使我把它连接到商店上,我似乎看不到组件中呈现的值
this.props在
componentDidMount and render(){}
上未定义。但是,同一组件上的按钮不会触发startTimer操作,因此它正在更新状态,那么为什么组件不反映它,为什么组件中未定义my this.props值?哦,是的,只需添加我的另外两个redux reducer/操作就可以很好地工作,即使它们正在使用
thunk
中间件执行fetch/promise。欢迎提供任何帮助/建议,因为这是我应用程序的最后一个障碍

代码如下:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";

import thunk from 'redux-thunk';
import reducers from './reducers'

export const store = createStore(reducers, applyMiddleware(thunk));

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
行动

import { getForecast } from "../api/GET/getForecast";
import { getCurrentWeather } from "../api/GET/getCurrentWeather";

export const fetchCurrentWeather = () => async (dispatch, getState) => {
  const { name, dt, main } = await getCurrentWeather();

  const cityProperties = { name, dt, main };

  dispatch({ type: "CURRENT_WEATHER", payload: cityProperties });
};

export const fetchForecasts = () => async (dispatch) => {
  const { list } = await getForecast();

  dispatch({ type: "FORECAST_WEATHER", payload: list });
};

定时器组件

import React, { useState, useEffect } from "react";
import "./Timer.scss";
import { connect } from "react-redux";
import { start, stop, tick } from "../../actions";

class Timer extends React.Component {
  constructor(props) {
    super(props);
  }

  handleStop = () => {
    clearInterval(this.props.timerId);
    this.props.stopTimer();
  };

  componentDidMount() {
    console.log("TIMER PROPS IS UNDEFINED HERE", this.props);
  }

  render() {
    const { timerTime } = this.props;

    console.log("PROPS ARE ALSO UNDEFINED HERE", this.props);

    return (
      <div className="timer-container">
        <button onClick={this.props.startTimer}>Start</button>
        TIME IS: {timerTime}
        <button onClick={this.handleStop}>Stop</button>
        <button onClick={this.props.resetTimer}>Reset</button>
      </div>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return {
    timerOn: state.timerOn,
    timerStart: state.timerStart,
    timerTime: state.timerTime,
    timerId: state.timerId,
  };
};

const mapDispatchToProps = (dispatch) => {
  console.log("dispatch", dispatch);
  let timerId;

  return {
    startTimer: () => {
      timerId = setInterval(() => dispatch({ type: "TICK" }), 1000);
      dispatch({ type: "START_TIMER", timerId });
    },
    stopTimer: () => {
      dispatch({ type: "STOP_IT" });
      clearInterval(timerId);
    },
    resetTimer: () => dispatch({ type: "RESUME_IT" }),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Timer);
import React,{useState,useffect}来自“React”;
导入“/Timer.scss”;
从“react redux”导入{connect};
从“../../actions”导入{开始、停止、勾选};
类计时器扩展了React.Component{
建造师(道具){
超级(道具);
}
handleStop=()=>{
clearInterval(this.props.timerId);
this.props.stopTimer();
};
componentDidMount(){
log(“此处未定义计时器道具”,this.PROPS);
}
render(){
const{timerTime}=this.props;
log(“这里也未定义道具”,this.PROPS);
返回(
开始
时间是:{timerTime}
停止
重置
);
}
}
const mapStateToProps=(state,ownProps)=>{
返回{
泰米隆:州,泰米隆,
timerStart:state.timerStart,
timerTime:state.timerTime,
timerId:state.timerId,
};
};
const mapDispatchToProps=(调度)=>{
控制台日志(“调度”,调度);
让时光流逝;
返回{
startTimer:()=>{
timerId=setInterval(()=>dispatch({type:“TICK”}),1000;
分派({类型:“启动计时器”,timerId});
},
停止计时器:()=>{
分派({type:“STOP_IT”});
清除间隔(timerId);
},
resetTimer:()=>分派({type:“RESUME_IT”}),
};
};
导出默认连接(MapStateTops、mapDispatchToProps)(计时器);
连接到存储区的其他组件按预期工作

import React from "react";
import "./Header.scss";

import Timer from "../Timer";
import { connect } from "react-redux";
import { fetchCurrentWeather } from "../../actions";

class Header extends React.Component {
  componentDidMount() {
    this.props.fetchCurrentWeather();
    console.log(this.props.currentWeather);
  }

  render() {
    const { name, dt, temp } = this.props.currentWeather
    return (
      <div className="top-header">
        <div className="current-city info">
          <h1>{name}</h1>
          <div className="time-container">
            <i className="time-icon icon" >xxx</i>
            <span className="time-text">{dt}</span>
            <i className="time-icon icon" >xxx</i>
          </div>
        <span className="degrees">{temp}&#176;</span>
        </div>

        <Timer />
      </div>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return { currentWeather: state.currentWeather };
};

export default connect(mapStateToProps, { fetchCurrentWeather })(Header);

从“React”导入React;
导入“/Header.scss”;
从“./Timer”导入计时器;
从“react redux”导入{connect};
从“../../actions”导入{fetchCurrentWeather};
类头扩展了React.Component{
componentDidMount(){
this.props.fetchCurrentWeather();
console.log(this.props.currentWeather);
}
render(){
const{name,dt,temp}=this.props.currentWeather
返回(
{name}
xxx
{dt}
xxx
{temp}°;
);
}
}
const mapStateToProps=(state,ownProps)=>{
返回{currentWeather:state.currentWeather};
};
导出默认连接(MapStateTops,{fetchCurrentWeather})(标头);
另一个连接到存储的有效组件

import React, { useState, useEffect } from "react";
import "./WeatherCard.scss";
import {fetchForecasts} from '../../actions';

import {connect} from 'react-redux';

class WeatherCard extends React.Component {
  constructor(props) {
    super(props);

  }

  componentDidMount(){
    this.props.fetchForecasts();

    console.log('PROPS IS DEFINED HERE', this.props);
  }

  render() {
    const allRelevantData = Object.entries(this.props.forecast).map(([key, value]) => {
      const dateTime = new Date(value.dt * 1000);
      const day = dateTime.toString().slice(0, 3);

      const item = {
        day: day,
        temp: Math.round(value.main.temp),
        weatherMetaData: value.weather[0],
      };

      return item;
    });

    const uniqueForecasts = Array.from(
      new Set(allRelevantData.map((a) => a.day))
    ).map((day) => {
      return allRelevantData.find((a) => a.day === day);
    });

    return uniqueForecasts.map(({ day, temp, weatherMetaData }, index) => {
      if (index < 5) {
        return (
          <div className="weather-card" key={index}>
            <div className="day-temperature-container">
              <span className="day">{day}</span>
              <span className="temperature fade-in">{temp}&#176;</span>
            </div>
            <div className="weather-description">
              <span
                className="icon weather"
                style={{
                  background: `url(http://openweathermap.org/img/wn/${weatherMetaData.icon}.png)`,
                }}
              />
              <p>{weatherMetaData.description}</p>
            </div>
          </div>
        );
      }
    });
  }
}

const mapStateToProps = (state, ownProps) => {
  return {forecast: state.forecast};
};

export default connect(mapStateToProps, {fetchForecasts})(WeatherCard);
import React,{useState,useffect}来自“React”;
导入“/WeatherCard.scss”;
从“../../actions”导入{FetchForecast};
从'react redux'导入{connect};
类WeatherCard.Component{
建造师(道具){
超级(道具);
}
componentDidMount(){
this.props.fetchForecast();
log('这里定义了PROPS',this.PROPS);
}
render(){
const allRelevantData=Object.entries(this.props.forecast).map([key,value])=>{
const dateTime=新日期(value.dt*1000);
const day=dateTime.toString().slice(0,3);
常数项={
天:天,
温度:数学四舍五入(值主温度),
weatherMetaData:value.weather[0],
};
退货项目;
});
const uniqueforecast=Array.from(
新设置(allRelevantData.map((a)=>a.day))
).map((天)=>{
返回所有相关数据。查找((a)=>a.day===day);
});
返回uniqueForecasts.map({day,temp,weatherMetaData},index)=>{
如果(指数<5){
返回(
{day}
{temp}°;
{weatherMetaData.description}

); } }); } } const mapStateToProps=(state,ownProps)=>{ 返回{forecast:state.forecast}; }; 导出默认连接(mapStateToProps,{FetchForecast})(天气卡);
听起来您在从redux reducer状态拔出时遇到了问题

通常我会

  • 在我的组件中,我将设置一个useffect()或componentDidMount来启动我的setInterval()函数。如果计时以秒为单位,则设置间隔功能将每1000毫秒运行一次
  • 2.)在我的setInterval函数中,我将在间隔的每次迭代中调度一个操作,以增加减速器的初始状态值0++(currentValue++)

    3.)在我的组件中,我将向组件传递道具。确保检查值是否需要映射或直接传入而不使用.map函数


    我也建议使用。使用该库,您可以轻松地完成所有这些操作。

    您需要从状态树中提取状态,该状态树由减缩器形成。你有三个减速机。 在Timer.js文件中,您需要从由currentTimereducer塑造的状态中提取状态。 如果在Timer.js中更改MapStateTops,如下所示;您可以获得以下状态:

    Timer.js

    ...
    //pulling of states from the state tree that shaped with currentTime reducer
    const mapStateToProps = (state) => {
      return {
        timerOn: state.currentTime.timerOn,
        timerStart: state.currentTime.timerStart,
        timerTime: state.currentTime.timerTime,
        timerId: state.currentTime.timerId,
      };
    };
    
    不相关,但我只是想推广使用redux logger:) reducer.js

    ...
    //Create Store 
    
    // import { createLogger } from 'redux-logger';
    const loggerMiddleware = createLogger();
    
    const rootReducer = combineReducers({
        currentWeather: currentWeatherReducer,
        forecast: forecastReducer,
        currentTime: currentTimeReducer
    })
    
    export const store = createStore(
        rootReducer,
        applyMiddleware(
            thunkMiddleware,
            loggerMiddleware
        )
    );
    
    妈的,我得去拿我的
    ...
    //Create Store 
    
    // import { createLogger } from 'redux-logger';
    const loggerMiddleware = createLogger();
    
    const rootReducer = combineReducers({
        currentWeather: currentWeatherReducer,
        forecast: forecastReducer,
        currentTime: currentTimeReducer
    })
    
    export const store = createStore(
        rootReducer,
        applyMiddleware(
            thunkMiddleware,
            loggerMiddleware
        )
    );