- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于reactJs和redux来说还很陌生,尽管有教程(包括redux中的todolist示例),我仍然很难理解如何实际触发将改变状态的操作。
我已经构建了一些非常简单的东西,并且加载良好。有人可以帮助我发送一个操作,最终导致商店数据被更改吗?
我希望当用户单击 li.module 时调用togglePriceModule 函数。我是否需要调用作为 props 传递给子组件的主 Pricing 组件的函数?正确的做法是什么?
非常感谢!
我的app.js:
//Importing with braces imports a specific export of the file
import { createDevTools } from 'redux-devtools'
//Importing without braces imports the default export of the file
import LogMonitor from 'redux-devtools-log-monitor'
import DockMonitor from 'redux-devtools-dock-monitor'
import React from 'react'
import ReactDOM from 'react-dom'
//Redux helps manage a single state which can be updated through actions call pure reducers
//Importing muliple items injects them into the current scope
import { applyMiddleware, compose, createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
//React-router helps switch between components given a specific route
import { Router, Route, Link } from 'react-router'
import createHistory from 'history/lib/createHashHistory'
import { syncHistory, routeReducer } from 'react-router-redux'
//Imports an object of elements correspondings to every export of the file
import * as reducers from './reducers';
import Pricing from './components/pricing/pricing_main.js';
const history = createHistory();
const middleware = syncHistory(history);
const reducer = combineReducers({
...reducers,
routing: routeReducer
});
const DevTools = createDevTools(
<DockMonitor toggleVisibilityKey="ctrl-q"
changePositionKey="ctrl-alt-q"
defaultIsVisible={false}>
<LogMonitor theme="tomorrow" preserveScrollTop={false} />
</DockMonitor>
);
const finalCreateStore = compose(
applyMiddleware(middleware),
DevTools.instrument()
)(createStore);
const store = finalCreateStore(reducer);
middleware.listenForReplays(store);
var renderComponent = function(component, id) {
var reactContainer = document.getElementById(id);
if (null !== reactContainer) {
ReactDOM.render(
<Provider store={store}>
<div>
<Router history={history}>
<Route path="/" component={component} />
</Router>
<DevTools />
</div>
</Provider>,
reactContainer
);
}
};
renderComponent(Pricing, 'react-pricing');
我的定价组成部分:
import React from 'react';
var _ = require('lodash');
const Pricing = React.createClass({
getInitialState: function(){
return {
modules: {
'cms' : {
title: 'Fiches techniques & Mercuriale',
subtitle: 'Gérez votre connaissance sous un format structuré',
price: 15,
details: [
'première ligne',
'deuxième ligne',
'troisième ligne'
],
'activated': true
},
'cycle' : {
title: 'Cycle de menus',
subtitle: 'Programmez votre production dans le temps',
price: 20,
details: [
'première ligne',
'deuxième ligne',
'troisième ligne'
],
'activated': false
},
'organigram' : {
title: 'Organigramme de production',
subtitle: "Optimisez l'affectation de votre main d'oeuvre",
price: 20,
details: [
'première ligne',
'deuxième ligne',
'troisième ligne'
],
'activated': false
},
'teams' : {
title: 'Planning des équipes',
subtitle: "Gérez les temps de présence de vos salariés",
price: 20,
details: [
'première ligne',
'deuxième ligne',
'troisième ligne'
],
'activated': false
},
'orders' : {
title: 'Commandes et stocks',
subtitle: "Commandez en un clic auprès de vos fournisseurs",
price: 20,
details: [
'première ligne',
'deuxième ligne',
'troisième ligne'
],
'activated': false
}
},
options : {
users: {
title: "Nombre d'utilisateurs",
subtitle: "Distribuez des accès sécurisés",
price: 5,
unit: "5€ par utilisateur",
type: 'quantity',
value: 1
},
sites: {
title: 'Sites de vente ou de production',
subtitle: "Gérez vos multiples sites dans la même interface",
unit: "50€ par site",
type: 'quantity',
value: 1
},
backup: {
title: 'Sauvegarde',
subtitle: "Recevez une copie Excel de vos données tous les jours",
type: 'switch',
value: 'day'
}
}
}
},
componentWillMount: function(){
this.setState(this.getInitialState());
},
render: function () {
return (
<div className="wrapper">
<h1>Paramétrez votre offre</h1>
<div id="elements">
<ul id="module-container" className="flex-container col">
{_.map(this.state.modules, function(module, key) {
return <Module key={key} data={module} />
})}
</ul>
<ul id="param_container">
{_.map(this.state.options, function(option, key) {
return <Option key={key} data={option} />
})}
</ul>
</div>
<div id="totals" className="flex-container sp-bt">
<span>Total</span>
<span>{calculatePrice(this.state)}</span>
</div>
</div>
);
}
});
function calculatePrice(state) {
var modulePrices = _.map(state.modules, function(item){
return item.price;
});
modulePrices = _.sum(modulePrices);
return modulePrices;
}
var Module = React.createClass({
render: function(){
var data = this.props.data;
return <li className="module">
<div className="selection">
<i className={data.activated ? 'fa fa-check-square-o' : 'fa fa-square-o'} />
</div>
<div className="title">
<h3>{data.title}</h3>
<h4>{data.subtitle}</h4>
</div>
<div className="price">
<div className="figure">{data.price}</div>
<div className="period">par mois</div>
</div>
<ul className="details">{
data.details.map(function(item, key){
return <li key={key}><i className="fa fa-check" />{item}</li>
})}
</ul>
</li>
}
});
var Option = React.createClass({
render: function(){
var data = this.props.data;
return <li className="param">
<div className="title">
<h3>{data.title}</h3>
<h4>{data.subtitle}</h4>
</div>
<div className="config">
<span className="figure"><i className="fa fa-minus" /></span>
<input value="1"/>
<span className="plus"><i className="fa fa-plus" /></span>
</div>
</li>
}
});
export default Pricing;
我的行动:
import { TOGGLE_PRICE_MODULE, INCREASE_PRICE_OPTION, DECREASE_PRICE_OPTION } from '../constants/constants.js'
export function increasePriceOption(value) {
return {
type: INCREASE_PRICE_OPTION,
value: value
}
}
export function decreasePriceOption(value) {
return {
type: DECREASE_PRICE_OPTION,
value: value
}
}
export function togglePriceModule(activated) {
return {
type: TOGGLE_PRICE_MODULE,
activated: activated
}
}
我的 reducer :
import { TOGGLE_PRICE_MODULE, INCREASE_PRICE_OPTION, DECREASE_PRICE_OPTION } from '../constants/constants.js'
export default function updateModule(state = false, action) {
if(action.type === TOGGLE_PRICE_MODULE) {
return !state;
}
return state
}
export default function updateOption(state = 1, action) {
if(action.type === INCREASE_PRICE_OPTION) {
return state + 1;
}
else if(action.type === DECREASE_PRICE_OPTION) {
if (state < 2) {
return 1;
} else {
return state + 1;
}
}
return state
编辑 1
我已经隔离了模块组件,并尝试根据下面的第一个答案进行调整:模块正确加载,但 View 中根本没有任何效果。缺少一些东西吗?
第一个错误:我需要改变
import * as reducers from './reducers';
进入
import * as reducers from './reducers/pricing.js';
控制台日志实际显示我的 reducer 。
为什么?
第二:console.log 显示该操作确实被调用 reducer 中的情况相同表明事实并非如此。我应该如何在reducer和action之间建立链接?我应该使用 mapStateToProps 并以某种方式连接吗?
import React from 'react';
import { togglePriceModule } from '../../actions/pricing.js';
var Module = React.createClass({
handleClick: function(status){
this.context.store.dispatch(togglePriceModule(status));
},
render: function(){
console.log(this.props);
var data = this.props.data;
return <li className="module" onClick={this.handleClick}>
<div className="selection">
<i className={data.activated ? 'fa fa-check-square-o' : 'fa fa-square-o'} />
</div>
<div className="title">
<h3>{data.title}</h3>
<h4>{data.subtitle}</h4>
</div>
<div className="price">
<div className="figure">{data.price}</div>
<div className="period">par mois</div>
</div>
<ul className="details">{
data.details.map(function(item, key){
return <li key={key}><i className="fa fa-check" />{item}</li>
})}
</ul>
</li>
}
});
Module.contextTypes = {
store: React.PropTypes.object
};
export default Module;
}
编辑2
我已按照建议进行了更改,现在调用了 reducer 。但是我没有更改用户界面,所以我猜测我做错了什么。 我处理状态/商店/ Prop 的方式正确吗?
该 bundle 有效,但我在控制台中收到以下错误:
warning.js:45 Warning: setState(...): Cannot update during an existing state transition (such as within
render
). Render methods should be a pure function of props and state.
此外,我是否应该将函数从定价组件(容器)传递到模块组件并将逻辑放在上面,而不是在子模块组件中分派(dispatch)操作?
我更新的模块组件,我点击它希望 UI 发生变化:
import React from 'react';
import { connect } from 'react-redux';
import { togglePriceModule } from '../../actions/pricing.js';
var Module = React.createClass({
handleClick: function(status){
this.context.store.dispatch(togglePriceModule(status));
},
render: function(){
var data = this.props.data;
return <li className="module" onClick={this.handleClick(!data.activated)}>
<div className="selection">
<i className={data.activated ? 'fa fa-check-square-o' : 'fa fa-square-o'} />
</div>
<div className="title">
<h3>{data.title}</h3>
<h4>{data.subtitle}</h4>
</div>
<div className="price">
<div className="figure">{data.price}</div>
<div className="period">par mois</div>
</div>
<ul className="details">{
data.details.map(function(item, key){
return <li key={key}><i className="fa fa-check" />{item}</li>
})}
</ul>
</li>
}
});
Module.contextTypes = {
store: React.PropTypes.object
};
function mapStateToProps(state) {
return {
data: state.updateModule.data
}
}
export default connect(mapStateToProps)(Module)
export default Module;
我的行动:
export function togglePriceModule(status) {
return {
type: TOGGLE_PRICE_MODULE,
activated: status
}
}
我的 reducer :
import { TOGGLE_PRICE_MODULE, INCREASE_PRICE_OPTION, DECREASE_PRICE_OPTION } from '../constants/constants.js'
export function updateModule(state = {}, action) {
console.log('updateModule reducer called');
if(action.type === TOGGLE_PRICE_MODULE) {
return {...state, activated : action.activated };
}
return state
}
export function updateOption(state = {}, action) {
if(action.type === INCREASE_PRICE_OPTION) {
return {...state, value: state.value + 1};
} else if(action.type === DECREASE_PRICE_OPTION) {
if (state.value < 2) {
return {...state, value : 1};
} else {
return {...state, value : state.value - 1};
}
}
return state
}
最佳答案
首先dispatch是一个存储函数。您需要将商店作为引用,然后导入您的操作并调度它。 reducer 将处理逻辑并返回将触发渲染的新状态。
添加此:
Pricing.contextTypes = {
store: React.PropTypes.object
};
您应该有商店引用信息。
然后只需导入您的操作:
import myAction from './myPath'
然后通过这样做:
this.context.store.dispatch(myAction(myVar));
这将触发调度,该调度将返回新状态并触发渲染。
例如:
handleClick() {
this.context.store.dispatch(myAction());
}
和内部渲染:
<a onClick={this.handleClick}>test</a>
我在那里使用 ES6 语法。
基本上这个过程应该非常简单,除非我在你的问题中遗漏了一些东西。
或者,如果你在 console.log(this.props) 中看到调度,你可以:
this.props.dispatch(myAction(myVar));
回答你的这两个问题:我应该如何在reducer和action之间建立联系?我应该使用 mapStateToProps 并以某种方式连接吗?
是的,您必须在组件中导入 connect 才能与商店建立链接:
import { connect } from 'react-redux';
是的,您需要将状态映射到 Prop :
function mapStateToProps(state) {
return {
myVar: state.myReducer.myVar
}
}
最后使用 connect 将所有内容包装在一起。
export default connect(mapStateToProps)(Pricing)
关于javascript - ReactJs Redux : how to dispatch an action on a user event and link actions with the reducers and the store,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36901292/
我通常从以下位置获取代码:https://www.w3schools.com .这个代码还有一个 Accordion ; 但是,当我使用链接 -> 到 Accordion 时, Accordion 不
我见过的所有 JNI 指南(例如 JNI runtime linking )都建议我将 JNI 库链接到 libjvm.so: $ gcc -I${JAVA_HOME}/include -c -o t
实现以下目标的正确 URL 格式是什么: 使用 Universal Link 在 iOS 上的另一个应用程序中打开 Google map 应用程序。 根据两个坐标设置目的地:纬度和经度,并让用户选择交
我已经查看了 Microsoft 的 MSDN 和整个网络,但我仍然无法很好地了解它是什么。 这是否意味着已完成的程序在执行期间的不同时间加载 DLL,而不是在启动时一次性加载所有 DLL? 我完全偏
我有一个看起来像这样的 css: .browse-link A:link { color: #F6CA4C; text-decoration: none; } .browse-link
当我点击“产品”链接时,它突然指向#link。我怎样才能使它的外观看起来像滚动然后转到产品?请帮帮我。 vStudy function big(x){
我想在保存之前更改从输入字段中获取的值。 params[:link]['url'] = "www.facebook.com/redbull" 现在我只想将“redbull”放入数据库。以下代码失败,因
我正在使用链表编写程序(真是一场噩梦)。 无论如何,该程序的目的是输入 8 个字符,然后让程序将字符打印回给您,并以相反的顺序打印回字符,当然是使用链表。 到目前为止我已经明白了。它有很多错误(我认为
基本上,我删除了 anchor 按钮,因此链接窗口中不应该有指向 anchor 选项的链接。 有什么方法可以删除该下拉选项 ? 最佳答案 想通了 if ( dialogName == 'link' )
我的本地(和远程)SQL SERVER 2005 管理员都声称“允许链接服务器是一个安全问题”并禁止在此处使用它们。 (哈?) 无论如何,有没有办法在没有链接服务器的情况下做类似的事情? SELE
如果我有: linkedlist1= 1,2,3,4; 和 linkedlist2= 5,6,7; 如果我调用: linkedlist2.set(0,9999) 它会更改为 linkedlist2 =
首先,如果这个问题看起来很愚蠢,我很抱歉,但我仍在学习 React 和 html。所以问题是我的 react 代码中有一个按钮标签,它为我提供了一些关于进入我提供的特定链接的逻辑。我的 Button.
我将制作一个文本 block ,这样如果您单击一个单词,它就会被词汇替代品所替换。 例如“fearful-of-cats”是“ailurophobic”的词汇替代品,因为如果您在任何文本中将后者替换为
我有以下代码 Can you click me? 目标是我可以点击“你能点击我吗”框并转到 google 并在包含 div 的任何其他地方
这是一个案例: 默认情况下,如果我点击#2、#3、#4、#5,我将被重定向到#1。 如果我想在没有 #1 激活的情况下点击输入,我该如何修复 CSS? 提前
有没有什么快速的方法可以使 :visited 链接的颜色与链接本身的颜色相同? 例如: * {color:black} a:link {color:blue} a:visited {color:inh
我读到从 iOS 9 开始,引入了通用链接。请解释深层链接和通用链接之间的区别。我的目标是,一个链接将通过邮件发送给客户。让邮件说有一个项目 A 的报价和一个链接。单击链接时 如果安装了该应用程序,则
因此我们需要对 CSS anchor 伪类使用以下顺序 a:link { color: red } a:visited { color: blue } a:hover { color
我组件的当前路径是http://localhost:3000/dashboard/questionnaire/5bf79ff4c45a150015cef7a9在这个组件里面有 Financials 如
我 rsync 目录“Promotion”包含两台具有不同目录结构的机器之间的绝对符号链接(symbolic link)。因此绝对符号链接(symbolic link)在两台机器上都不起作用。为了使它
我是一名优秀的程序员,十分优秀!