我如何从另一个React组件访问Redux状态?

时间:2020-01-18 03:10:54

标签: javascript reactjs redux react-redux

我正在开发一个彩票统计应用程序,该应用程序从输入中加载的csv中获取数据,然后我想将此数据读取到redux存储中,以便可以在多个组件中使用它。

导入文件并通过Header.js并使用动作读取文件后,我已成功将数据保存到redux存储中,但是我不确定如何在其他组件(例如Main.js。

我觉得我仍然对React / redux如何组合在一起感到困惑。很抱歉,是否曾经有人问过我,但是我在网上查找的所有内容都无法正常工作。

// index.js

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

import App from "./components/App";

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

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector("#root")
);
// App.js

import React from "react";

import Header from "./Header";
import Main from "./Main";

const App = () => {
  return (
    <div>
      <Header />
      <Main />
      <div className="numbers-for-draw"></div>
    </div>
  );
};

export default App;
// Header.js

import React from "react";
import { CSVReader } from "react-papaparse";
import { fetchData } from "../actions";
import { connect } from "react-redux";

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.fileInput = React.createRef();
  }

  handleReadCSV = data => {
    this.props.fetchData(data);
    console.log(this.props.data);
  };

  handleOnError = (err, file, inputElem, reason) => {
    console.log(err);
  };

  handleImportOffer = () => {
    this.fileInput.current.click();
    console.log("Got to handleImportOffer");
  };

  render() {
    return (
      <header>
        <CSVReader
          onFileLoaded={this.handleReadCSV}
          inputRef={this.fileInput}
          style={{ display: "none" }}
          onError={this.handleOnError}
        />
        <button onClick={this.handleImportOffer}>Import</button>
      </header>
    );
  }
}

//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
  data: state.data
});

export default connect(mapStateToProps, {
  fetchData: fetchData
})(Header);
// Main.js

import React from "react";

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

const Main = () => {
  console.log("In main");
  console.log(this.props.data);  //Blows up here. 
  return <div>Main</div>;
};

//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
  data: state.data
});

export default connect(mapStateToProps, {
  fetchData: fetchData
})(Main);
// actions/index.js

export const fetchData = data => dispatch => {
  console.log("Action");
  const lottoData = {
    stringNumbers: [
      "one",
      "two",
      "three",
      ...
    ],

    allResults: [],
    winningNumbers: [],
    winningNumbersAsStrings: []
  };

  const localData = data.data;
  localData.shift();

  localData.forEach(line => {
    const lineObject = {
      draw: line[0],
      drawDate: line[1],
      ballOne: line[2],
      ballTwo: line[3],
      ballThree: line[4],
      ballFour: line[5],
      ballFive: line[6],
      ballSix: line[7],
      bonusBall: line[8],
      bonusBall2: line[9],
      powerBall: line[10]
    };

    lottoData.allResults.push(lineObject);

    let nums = [];
    nums.push(parseInt(line[2]));
    nums.push(parseInt(line[3]));
    nums.push(parseInt(line[4]));
    nums.push(parseInt(line[5]));
    nums.push(parseInt(line[6]));
    nums.push(parseInt(line[7]));

    nums.sort((a, b) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });

    lottoData.winningNumbers.push(nums);
    lottoData.winningNumbersAsStrings.push(nums.toString());
  });

  dispatch({ type: "FETCH_DATA", payload: lottoData });
};

// lottoReducer.js

export default (state = {}, action) => {
  switch (action.type) {
    case "FETCH_DATA":
      return action.payload;
    default:
      return state;
  }
};
// reducers/index.js

import { combineReducers } from "redux";
import lottoReducer from "./lottoReducer";

export default combineReducers({
  data: lottoReducer
});

2 个答案:

答案 0 :(得分:2)

我尚未测试您的代码,但在我看来,唯一的问题出在您的Main.js

虽然您使用function component而不是课程,但不应使用this来访问道具。以下应该可以正常工作:

const Main = (props) => {
  console.log("In main");
  console.log(props.data);  
  return <div>Main</div>;
};

//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
  data: state.data
});

export default connect(mapStateToProps, {
  fetchData: fetchData
})(Main);

答案 1 :(得分:1)

在main.js中,您使用了功能组件,因此this.props在这里不起作用。您必须将道具传递到组件和console.log(props.data)