首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >即使存储已更新,Redux也不会重新呈现React组件

即使存储已更新,Redux也不会重新呈现React组件
EN

Stack Overflow用户
提问于 2017-07-23 17:37:22
回答 2查看 554关注 0票数 1

您好,我是Redux的新手,我正在使用React和Redux尝试构建一个UI,在其中我可以将文件(在这种情况下是发票)拖放到UI的一部分,在列表中呈现它们,然后能够启动一个弹出窗口来编辑与每个发票关联的元数据。拖放都很好- Redux在每次拖放文件并更新列表时都会重新渲染视图。但是,当我尝试单击每个发票上的编辑按钮时,商店正在更新,但我的popover组件中的道具没有更新。实际上,当我尝试单击编辑发票按钮时,看起来根本没有发生任何重新渲染

App.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import AddInvoice from '../containers/AddInvoice'
import CurrentInvoiceList from '../containers/CurrentInvoiceList'
import ControlPopover from '../containers/ControlPopover'

const App = () => (
  <div>
    <AddInvoice />
    <CurrentInvoiceList />
    <ControlPopover />
  </div>
)

export default App

containers/AddInvoice.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import { connect } from 'react-redux'
import { addInvoice } from '../actions'

const recipientDataDefaults = {
  name: '',
  surname: '',
  address: '',
  phone: ''
};

const handleDragOver = event => {
  event.stopPropagation();
  event.preventDefault();
  event.dataTransfer.dropEffect = 'copy';
};

const handleDragEnter = event => {
  event.stopPropagation();
  event.preventDefault();
};

const handleDragLeave = event => {
  event.stopPropagation();
  event.preventDefault();    
};

let AddInvoice = ({ dispatch }) =>
  const styles = {'minHeight': '200px', 'background': 'tomato'}
  return (
    <div style={styles}
         onDragEnter={handleDragEnter} 
         onDragLeave={handleDragLeave} 
         onDragOver={handleDragOver} 
         onDrop={event => {
           event.stopPropagation(); 
           event.preventDefault();
           const data  = event.dataTransfer;
           const files = data.files;

           const newInvoiceUploads = Object.keys(files)
             .map(key => files[key])
             .map(file => {
               const invoiceObject = {};
               invoiceObject.files = [file];
               invoiceObject.recipientData = Object.assign({}, recipientDataDefaults);
               return invoiceObject;
             });

           newInvoiceUploads.forEach(invoice => dispatch(addInvoice(invoice)))

    }}>
      Drag an invoice here to upload
    </div>
  )
}
AddInvoice = connect()(AddInvoice)

export default AddInvoice

containers/ControlPopover.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { connect } from 'react-redux'
import { closePopoverWithoutSave } from '../actions'
import Popover from '../components/Popover/Popover'

const mapStateToProps = (state) => {
  return {
    isActive: !!state.isActive
  }
}

const mapDispatchToProps = {
  handleCancel: closePopoverWithoutSave
}


const ControlPopover = connect(
  mapStateToProps,
  mapDispatchToProps
)(Popover)

export default ControlPopover

containers/CurrentInvoiceList.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { connect } from 'react-redux'
import { showInvoiceEditPopover } from '../actions'
import InvoiceList from '../components/InvoiceList/InvoiceList'

const mapStateToProps = state => {
  return {
    invoices: state.invoices
  }
}

const mapDispatchToProps = dispatch => ({
  handleEditInvoice: invoice => {
    dispatch(showInvoiceEditPopover(invoice))
  }
})

const CurrentInvoiceList = connect(
  mapStateToProps,
  mapDispatchToProps
)(InvoiceList)

export default CurrentInvoiceList

操作/index.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let nextInvoiceId = 0
export const addInvoice = invoice => ({
  type: 'ADD_INVOICE',
  id: nextInvoiceId++,
  invoiceData: invoice
})

export const showInvoiceEditPopover = invoice => ({
  type: 'SHOW_POPOVER',
  invoice
})

popover reducer (在app中组合,但为了简洁,在这里内联) reducers/index.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const popover = (state = {}, action) => {
  switch (action.type) {
    case 'SHOW_POPOVER':
      const popoverState = {}
      popoverState.isActive = true
      popoverState.data = action.invoice
      return popoverState

     case 'CLOSE_POPOVER_WITHOUT_SAVING':
       const inactiveState = {}
       inactiveState.isActive = false
       inactiveState.data = {}
       return inactiveState;
     default:
       return state
   }
}

export default popover

components/InvoiceList.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import PropTypes from 'prop-types'
import Invoice from '../Invoice/Invoice'

const InvoiceList = ({ invoices, handleEditInvoice }) => {

return (
  <div>
    {invoices.map(invoice =>
      <Invoice
        key={invoice.id}
        invoice={invoice.invoiceData}
        onClick={event => {
          // here we invoke the action bound by the CurrentInvoiceList
          // container
          event.preventDefault()
          handleEditInvoice(invoice)
        }}
      />
    )}
  </div>
 )
}

InvoiceList.propTypes = {
  invoices: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    invoiceData: PropTypes.object
  }).isRequired).isRequired,
  handleEditInvoice: PropTypes.func.isRequired
}

export default InvoiceList

组件/Invoice.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import PropTypes from 'prop-types'
import TextInput from '../TextInput/TextInput';
import Button from '../Button/Button';
import './invoice.css'

const Invoice = ({ invoice, onClick }) => {

const fileNames = invoice.files.map((file, index) => {
    return (<div key={index} className="invoice__file-title-legend">
   {file.name}</div>);
  });

return (
    <div className="invoice">
    <form className="invoice__form">
    <TextInput id="invoice__input-amount" placeholder="enter invoice amount" label="Invoice Amount" />
    <TextInput id="invoice__input-target" placeholder="enter payment target" label="Payment Target" />
    <Button value="Add recipient" onClick={onClick} /> // clicking this button updates the store but does NOT re-render. Why?
  </form>

  <div className="invoice__files">{fileNames}</div>
</div>
  )
}

Invoice.propTypes = {
  onClick: PropTypes.func.isRequired,
  invoice: PropTypes.object
}

export default Invoice

组件/Popover/Popover.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import PropTypes from 'prop-types'
import createModifiers      from '../../lib/createModifiers';
import './Popover.css';

const Popover = ({ handleCancel, isActive }) => {
  console.log('rendering popover component') // does not get called when invoice edit button is pressed
  const popoverModifiers = createModifiers('popover', {
    'is-active': isActive
  })

  return (
    <div className={popoverModifiers}>
      <div className="popover__header">
        <button onClick={handleCancel}>x</button>
      </div>
      <div className="popover__content">
       Popover content
      </div>
    </div>
  )
}
Popover.propTypes = {
  handleCancel: PropTypes.func.isRequired,
  isActive: PropTypes.bool.isRequired 
}

export default Popover

最后是后人的createModifiers代码。此代码仅根据传入的状态布尔值生成一些BEM修饰符CSS类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createModifiers = (element, modifiers) => {
  const classList = Object.keys(modifiers)
    .filter(key => modifiers[key])
    .map(modifier => `${element}--${modifier}`)
    .concat(element)
    .join(' ')

  return classList
}

export default createModifiers

我知道这是大量的示例代码,所以我尽量保持简短和专注,同时给出应用程序的全面视图。任何帮助都是非常感谢的。

EN

回答 2

Stack Overflow用户

发布于 2017-07-23 18:08:20

我认为您的问题是您的mapDispatchToProp函数格式不正确。

您需要返回一个具有方法的对象。这些方法将作为道具提供给已连接的组件。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const mapDispatchToProps = ( dispatch ) => {
    return {
        doSomething: ( arguments ) => {
            // here you can dispatch and use your arguments
        } 
    };
}

doSomething是将被提供给连接的组件的支柱。

所有mapDispatchToProps函数的格式都不正确。

旁注/观点- TLDR

在未来,如果你有很多代码要发布,我相信如果这些片段链接在一起,会更容易消化。

也就是说。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// App.js
const App = () => (
    <div>
        <Header />
        <Body />
        <Footer />
    </div>
);

组件按以下顺序出现: header -> body -> footer。按此顺序提供它们的代码,并在一个块中包含它们的操作、缩减程序、表示形式和容器信息。

标题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// header.presentational.js ...

// header.container.js ... ( or where you mapStateToProps and connect )

// header.actions.js ...

// header.reducer.js ...

身体。

页脚...

我不知道您的代码是否有所不同,但是您的mapStateToDispatch函数的格式仍然不正确。

改变这个..。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const mapDispatchToProps = dispatch => ({
  handleEditInvoice: invoice => {
    dispatch(showInvoiceEditPopover(invoice))
  }
})

要这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const mapDispatchToProps = dispatch => ({
  return {
    handleEditInvoice: invoice => {
      dispatch(showInvoiceEditPopover(invoice))
    }
  };
})
票数 0
EN

Stack Overflow用户

发布于 2017-07-23 19:33:55

问题出在containers/ControlPopover.js和mapStateToProps函数中。需要将isActive属性分配给state.popover.isActive

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45268062

复制
相关文章
C#嵌入子窗体,判断子窗体是否打开了
/// <summary> /// 嵌入子窗体,判断子窗体是否打开了 /// </summary> public static Form1 f; public void Form1Show() { if (f == null || f.IsDisposed) { f = new Form1 {
landv
2019/03/19
2K0
C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)
本文转载:http://www.csframework.com/archive/2/arc-2-20110805-1771.htm
跟着阿笨一起玩NET
2018/09/18
8.4K0
C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)
c# winform 窗体失去焦点关闭(钩子实现)
main函数里面写 Application.ApplicationExit += Application_ApplicationExit;
冰封一夏
2019/09/10
2.9K0
c# 窗体最小化后截图实现
我们知道,当我们需要对Control进行截图时,我们可以使用Control.DrawToBitmap()进行截图,
冰封一夏
2019/09/11
1.2K0
窗体构造函数——c#
c#窗体构造函数比窗体加载函数Form1_Load()还要早,构造窗体最先运行的函数
vv彭
2020/12/16
1.3K0
c# 停靠窗体
public partial class FrmAnchor : Form, IMessageFilter { public FrmAnchor(Control parentControlc, Control keyControl) { InitializeComponent(); this.Size = keyControl.Size; this.HandleCreated += FrmDow
冰封一夏
2019/09/11
1K0
C# winform美化窗体
大家好,又见面了,我是你们的朋友全栈君。 记录一下winform美化工具CSkin 一个.Net的UI库。 参考链接:https://blog.csdn.net/yyl7727/article
全栈程序员站长
2022/09/01
1.3K0
弹出的模式窗体控制父窗体的方法
var strUrl = ‘test.php’; window.showModalDialog(strUrl, window, “dialogWidth:800px; dialogHeight:600px; dialogHide:yes; scroll:no; status:no”);
魏杰
2022/12/23
1.4K0
c# Winform 加载窗体
先来一个加载窗体代码 1 public partial class FrmLoading : Form 2 { 3 public BackgroundWorker updateDBWorker=new BackgroundWorker(); 4 5 public Action BackgroundWorkAction 6 { 7 get; 8 set; 9 } 10
冰封一夏
2019/09/10
1.5K0
C# 窗体常用API函数 应用程序窗体查找
常用的处理窗体的API函数如下(注意:API函数必须放在窗体中...): 使用C#语言,要引用DllImport,必须要添加using System.Runtime.InteropServices命名空间 (1)获得当前前台窗体句柄 [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]public static extern IntPtr GetForegroundWindow(); 返回值类型是IntPtr,即为当前
逸鹏
2018/04/10
4K0
C#将子窗体填充到父窗体的panel中
这里此窗体为lvlv_CauseForm 窗体,new一个窗体对象cf后,进行填充,代码如下:
恋喵大鲤鱼
2018/08/03
3.2K0
c#窗体应用程序怎么保存_importedfile用什么打开
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/09
6780
C# winform 窗体缩放失真
修改项目的配置文件,使项目运行时自动检测屏幕分辨率,在高分辨率屏幕禁用系统缩放,在项目应用程序清单文件里有对禁用高分屏自动缩放的支持
chuchur
2023/04/24
1.2K0
C#子窗体精确定位到父窗体的某个位…
弹出的子窗体精确定位在父窗体的某个位置,需要有目标坐标(这里将子窗体的位置设置为父窗体中一个panel的位置,需要将panel的坐标转换成屏幕坐标)
恋喵大鲤鱼
2018/08/03
1.4K0
C# Winform 窗体美化(目录)
最近在看 C# Winform 的窗体美化,发现一些很有用的美化皮肤库,学习过后也把一些资料整理一下。
全栈程序员站长
2022/09/02
1.5K0
C# WPF MVVM模式下在主窗体显示子窗体并获取结果
在winform中打开一个新的子窗体很简单,直接实例化窗体并show一下就可以:
用户9127601
2021/11/01
1.8K0
C# 线程中操作窗体控件
方法1: CheckForIllegalCrossThreadCalls = false;
zls365
2020/08/19
1.1K0
C# 线程中操作窗体控件
.NET CORE(C#) WPF亚克力窗体
使用 .Net Core 3.1 创建名为 “AcrylicWindow” 的WPF模板项目,添加三个Nuget库:MaterialDesignThemes、MaterialDesignColors和FluentWPF,其中亚克力效果是由FluentWPF控件库实现的。
沙漠尽头的狼
2020/01/16
2.3K0
【C#】带等待窗体的BackgroundWorker
---------------201504170911更新---------------
AhDung
2018/09/13
1.8K0
【C#】带等待窗体的BackgroundWorker
c#子窗口与父窗口_主窗体控制子窗体的显示
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170914.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/23
2.6K0

相似问题

关闭第二个窗体后,将textbox放在主窗体上

40

从第三个窗体打开第二个窗体

30

C#父窗体打开子窗体,在父窗体关闭后调用子函数。

13

vb。net等待第二个窗体关闭,然后再继续

30

c#关闭窗体更改值打开新窗体

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文