如何在多个组件中共享 redux 存储 [英] How to share redux store in multiple components
问题描述
我有一个组件,我将 redux 集成到我的 React 应用程序中.我正在打开第二个然后第三个组件.我不希望将我在第一个组件中获得的数据传递给 props 中的第二个然后第三个.
我想使用 redux store 来做到这一点.有没有办法做到这一点?
App.js
import React, { Component } from "react";从./logo.svg"导入标志;导入./App.css";从./RoundedButton"导入圆形按钮;从react-redux"导入{连接};从redux"导入 { bindActionCreators };从./actions/index"导入 * 作为动作;类 App 扩展组件 {构造函数(道具){超级(道具);this.state = {得分:0,地位: "",用户选择:"",计算机已选择:"",可见性:[真,真,真],按钮可见性:false};this.clickitem = this.clickitem.bind(this);this.handlePlayAgain = this.handlePlayAgain.bind(this);}handlePlayAgain() {this.setState({按钮可见性:假,可见性:[真,真,真]});}点击项目(用户){var url = "http://localhost:4000/generate-random";this.setState({ userSelected: 用户 });获取(网址).then(响应 => {如果(响应状态> = 400){throw new Error("来自服务器的错误响应");}返回 response.json();}).then(数据=> {var computer = data.item;this.setState({ computerSelected: 计算机 });如果 ((用户 === "摇滚" && 计算机 === "剪刀") ||(用户===纸"&&计算机===摇滚")||(用户===剪刀"&&计算机===纸")){this.props.increment();} else if (user === 计算机) {this.props.doNothing();} 别的 {this.props.decrement();}console.log(用户 + " " + 电脑);console.log("------------------------------------");App.contextTypes = { store: React.PropTypes.object };让商店= this.context.store;控制台日志(商店);数组变量 = [];var arrayvar = [];if (user === "Rock" && computer === "Rock") {arrayvar = [真,假,假];} else if (user === "Paper" && computer === "Paper") {arrayvar = [假,真,假];} else if (user === "剪刀" && 电脑 === "剪刀") {arrayvar = [假,假,真];}否则如果((用户 ===摇滚"&& 计算机 ===纸")||(用户===纸"&&计算机===摇滚")){arrayvar = [真,真,假];}否则如果((用户 === "摇滚" && 计算机 === "剪刀") ||(用户===剪刀"||计算机===摇滚")){arrayvar = [真,假,真];}否则如果((用户===纸"&&计算机===剪刀")||(用户===剪刀"||计算机===纸")){arrayvar = [假,真,真];}this.setState({可见性:arrayvar });this.setState({按钮可见性:true});});}使成为() {返回 (<div className="CenterDiv"><div className="AppTitle"><b>分数:{this.props.score}</b><div>{this.state.visibility[0]?<圆形按钮文字=摇滚"clickitem={this.clickitem}标签={this.state.userSelected === "摇滚" &&this.state.computerSelected === "摇滚"?用户和计算机选择": this.state.userSelected === "摇滚"?用户选择": this.state.computerSelected === "摇滚"?已选择计算机":""}/>: 空值}{this.state.visibility[1]?<圆形按钮文字=纸"clickitem={this.clickitem}标签={this.state.userSelected ===论文"&&this.state.computerSelected === "纸"?用户和计算机选择": this.state.userSelected == "Paper"?用户选择": this.state.computerSelected === "纸"?已选择计算机":""}/>: 空值}{this.state.visibility[2]?<圆形按钮文字=剪刀"clickitem={this.clickitem}标签={this.state.userSelected ===剪刀"&&this.state.computerSelected === "剪刀"?用户和计算机选择": this.state.userSelected === "剪刀"?用户选择": this.state.computerSelected === "剪刀"?已选择计算机":""}/>: 空值}
<div className="Status">{this.props.status}</div>{this.state.buttonVisibility?<button onClick={this.handlePlayAgain} style={{ margin: 30 }}>再玩一遍按钮>: 空值}
);}}函数 mapStateToProps(state) {返回 { 分数:state.score,状态:state.status };}导出默认连接(mapStateToProps,动作)(应用程序);
index.js
从react"导入React;从react-dom"导入 ReactDOM;从./App"导入应用程序;从./registerServiceWorker"导入 registerServiceWorker;导入./index.css";从react-redux"导入{提供者};import { createStore } from "redux";从./reducers"导入scoreReducer;让 store = createStore(scoreReducer);ReactDOM.render(<Provider store={store}><App/></Provider>,document.getElementById("root"));注册服务工作者();
secondcomponent.js
export default class SecondComponent extends Component {使成为() {返回 (//打印 redux 中的分数);}}
第三个组件.js
export default class ThirdComponent extends Component {使成为() {返回 (//打印 redux 中的分数);}}
在多个组件中访问 redux store 的方法是什么?
Any 用 connect
包装的组件:
connect(mapStateToProps, actions)(AnyComponent);
将可以访问整个 redux
商店.
使用mapStateToProps
,您可以通过props
将redux
存储中的相关数据传递给连接的组件.
关于组件内部 state
,我的经验法则是只为与特定组件相关的数据设置内部状态.
例如,下拉菜单的 extend
或 collapse
状态.
对于 ajax
请求,如果你已经在使用 redux
,我强烈建议使用带有 thunks
或 sagas
的操作> 并通过 redux
流传递新获取的数据:
Action/thunk -> Reducers -> 连接组件.
编辑
作为您评论的后续行动,
您不需要将要连接的每个组件都传递给 Provider,您只需传递一个根组件(在您的情况下为 App
),并且 App
的每个子组件都可以连接如有必要,redux
:
class SecondComponent 扩展组件 {使成为() {返回 (//打印 redux 中的分数<div>this.props.score</div>);}}导出默认连接(mapStateToProps)(第二组件);
以及其他组件:
class ThirdComponent 扩展组件 {使成为() {返回 (//打印 redux 中的分数<div>this.props.score</div>);}}导出默认连接(mapStateToProps)(第三组件);
编辑 #2
作为您其他评论的后续:
因此将道具中的值传递给组件或使用上述方法,idk 推荐哪个?
尽可能避免连接组件并将 props 传递给孩子,这样做的主要原因是为了防止对 redux
的依赖.
我更喜欢让我的组件尽可能愚蠢",让他们只关心事情的样子.
我确实有一些关注事物应该如何工作的组件,这些组件主要处理逻辑并将数据传递给孩子,它们是我经常连接的组件.
当我注意到我的应用程序正在扩展并且我的一些组件充当 props 的代理时(我什至有一个词!Propxy"),也就是说它们从它们的父级获取 props 并在没有使用它们,我通常会在组件树的中间注入一个连接的组件,这样我就可以让树流下的propxy"组件更轻更薄.
Hi I have one component in which I integrated the redux in my react application. I am opening second then third component. I don't want the pass the data which I obtained in first component to second then third in props.
I want to do this using redux store. Is there any way to do this ?
App.js
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import RoundedButton from "./RoundedButton";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as actions from "./actions/index";
class App extends Component {
constructor(props) {
super(props);
this.state = {
score: 0,
status: "",
userSelected: "",
computerSelected: "",
visibility: [true, true, true],
buttonVisibility: false
};
this.clickitem = this.clickitem.bind(this);
this.handlePlayAgain = this.handlePlayAgain.bind(this);
}
handlePlayAgain() {
this.setState({
buttonVisibility: false,
visibility: [true, true, true]
});
}
clickitem(user) {
var url = "http://localhost:4000/generate-random";
this.setState({ userSelected: user });
fetch(url)
.then(response => {
if (response.status >= 400) {
throw new Error("Bad response from server");
}
return response.json();
})
.then(data => {
var computer = data.item;
this.setState({ computerSelected: computer });
if (
(user === "Rock" && computer === "Scissors") ||
(user === "Paper" && computer === "Rock") ||
(user === "Scissors" && computer === "Paper")
) {
this.props.increment();
} else if (user === computer) {
this.props.doNothing();
} else {
this.props.decrement();
}
console.log(user + " " + computer);
console.log("------------------------------------");
App.contextTypes = { store: React.PropTypes.object };
let store = this.context.store;
console.log(store);
arrayvar = [];
var arrayvar = [];
if (user === "Rock" && computer === "Rock") {
arrayvar = [true, false, false];
} else if (user === "Paper" && computer === "Paper") {
arrayvar = [false, true, false];
} else if (user === "Scissors" && computer === "Scissors") {
arrayvar = [false, false, true];
} else if (
(user === "Rock" && computer === "Paper") ||
(user === "Paper" && computer === "Rock")
) {
arrayvar = [true, true, false];
} else if (
(user === "Rock" && computer === "Scissors") ||
(user === "Scissors" || computer === "Rock")
) {
arrayvar = [true, false, true];
} else if (
(user === "Paper" && computer === "Scissors") ||
(user === "Scissors" || computer === "Paper")
) {
arrayvar = [false, true, true];
}
this.setState({ visibility: arrayvar });
this.setState({
buttonVisibility: true
});
});
}
render() {
return (
<div className="CenterDiv">
<div className="AppTitle">
<b>Score: {this.props.score}</b>
<div>
{this.state.visibility[0]
? <RoundedButton
text="Rock"
clickitem={this.clickitem}
label={
this.state.userSelected === "Rock" &&
this.state.computerSelected === "Rock"
? "User & Computer Selected"
: this.state.userSelected === "Rock"
? "User Selected"
: this.state.computerSelected === "Rock"
? "Computer Selected"
: ""
}
/>
: null}
{this.state.visibility[1]
? <RoundedButton
text="Paper"
clickitem={this.clickitem}
label={
this.state.userSelected === "Paper" &&
this.state.computerSelected === "Paper"
? "User & Computer Selected"
: this.state.userSelected == "Paper"
? "User Selected"
: this.state.computerSelected === "Paper"
? "Computer Selected"
: ""
}
/>
: null}
{this.state.visibility[2]
? <RoundedButton
text="Scissors"
clickitem={this.clickitem}
label={
this.state.userSelected === "Scissors" &&
this.state.computerSelected === "Scissors"
? "User & Computer Selected"
: this.state.userSelected === "Scissors"
? "User Selected"
: this.state.computerSelected === "Scissors"
? "Computer Selected"
: ""
}
/>
: null}
</div>
<div className="Status">{this.props.status}</div>
{this.state.buttonVisibility
? <button onClick={this.handlePlayAgain} style={{ margin: 30 }}>
Play Again
</button>
: null}
</div>
</div>
);
}
}
function mapStateToProps(state) {
return { score: state.score, status: state.status };
}
export default connect(mapStateToProps, actions)(App);
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import registerServiceWorker from "./registerServiceWorker";
import "./index.css";
import { Provider } from "react-redux";
import { createStore } from "redux";
import scoreReducer from "./reducers";
let store = createStore(scoreReducer);
ReactDOM.render(
<Provider store={store}><App /></Provider>,
document.getElementById("root")
);
registerServiceWorker();
secondcomponent.js
export default class SecondComponent extends Component {
render() {
return (
// print score which is in redux
);
}
}
third component.js
export default class ThirdComponent extends Component {
render() {
return (
// print score which is in redux
);
}
}
Whats the way to have an access of redux store in multiple components ?
Any component that is wrapped with connect
:
connect(mapStateToProps, actions)(AnyComponent);
will have access to the entire redux
store.
With mapStateToProps
you can pass just relevant piece of data from the redux
store to the connected component via props
.
About component internal state
, my rule of thumb is to set internal state just for data that is relevant for the specific component.
For example, extend
or collapse
state for a Drop-down.
As for ajax
requests, if you already using redux
I highly recommend to use actions with thunks
or sagas
and pass the new fetched data through the redux
flow:
Action/thunk -> Reducers -> connected components.
Edit
As a followup to your comment,
You don't need to pass every component you want to connect to the Provider, you just pass a root component (App
in your case) and each child of App
can connect to redux
if necessary:
class SecondComponent extends Component {
render() {
return (
// print score which is in redux
<div>this.props.score</div>
);
}
}
export default connect(mapStateToProps)(SecondComponent);
And as well as for other components:
class ThirdComponent extends Component {
render() {
return (
// print score which is in redux
<div>this.props.score</div>
);
}
}
export default connect(mapStateToProps)(ThirdComponent);
Edit #2
As a followup to your other comment:
so passing value in props to components or use above said approach, Idk which is recommended ?
Avoid connecting components when you can and pass down the props to the children, the main reason for this is to prevent dependency on redux
.
I prefer keep my components "dumb" as i can and let them concern only on how things should look.
I do have some components that concern on how things should work and these components are mainly dealing with logic and passing down data to the children, they are the components i often connect.
When i notice that my app is scaling and some of my components are acting as a proxy of props (i even got a word for that! "Propxy"), that is they get props from their parent and pass them down without using them, i usually inject a connected component in the middle of the components tree so i can let the "propxy" components down the tree flow be more lighten and slim.
这篇关于如何在多个组件中共享 redux 存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!