如何在react redux中实现一个自包含组件?

2024-04-24

我正在基于react redux构建一个文件管理器webui(我的目的是通过这个项目掌握react和redux)

如您所知,文件管理器需要一个树浏览器。我想构建一个可以包含它自己并且每个都有自己状态的组件。像下面这样:

TreeNode可以包含子项TreeNode也是。每个TreeNode保持其状态{path, children_nodes, right .....}, children_nodes是从服务器获取的,path是由家长传递的。这就是我的想象。 结构如下:

App:
TreeNode
--TreeNode
----TreeNode
----TreeNode
TreeNode
TreeNode
--TreeNode
TreeNode
--TreeNode
----TreeNode
----TreeNode

但麻烦来了,因为 reduxconnect存储到树根,根下的所有节点接收相同的状态...

For example, I have a OPEN_NODE action, which is design to trigger getFileList fucntion base this node's path and set this node's state.open to true.(note: getFileList fucntion not implement yet, just give fake data for now) The screen shot: enter image description here

单击每个元素,但是states are equal.

My code:

容器/App.js

import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Footer from '../components/Footer';
import TreeNode from '../containers/TreeNode';
import Home from '../containers/Home';
import * as NodeActions from '../actions/NodeActions'

export default class App extends Component {

  componentWillMount() {
    // this will update the nodes on state
    this.props.actions.getNodes();
  }

  render() {
    const { nodes } = this.props
    console.log(nodes)
    return (
      <div className="main-app-container">
        <Home />
        <div className="main-app-nav">Simple Redux Boilerplate</div>
        <div>
          {nodes.map(node =>
            <TreeNode key={node.name} info={node} actions={this.props.actions}/>
          )}
        </div>

        {/*<Footer />*/}
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    nodes: state.opener.nodes,
    open: state.opener.open
  };
}


function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(NodeActions, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

容器/TreeNode.js

import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import classNames from 'classnames/bind'
import * as NodeActions from '../actions/NodeActions'

export default class TreeNode extends Component {

  constructor(props, context) {
    super(props, context)
    this.props = {
      open: false,
      nodes: [],
      info:{}
    }
  }

  handleClick() {
    let {open} = this.props
    if (open) {
      this.props.actions.closeNode()
    } else {
      this.props.actions.openNode()
    }
  }

  render() {
    const { actions, nodes, info } = this.props
    return (
      <div className={classNames('tree-node', { 'open':this.props.open})} onClick={ () => {this.handleClick()} }>
        <a>{info.name}</a>
        {nodes &&
          <div>{nodes.map(node => <TreeNode info={node} />)}</div>
        }
        {!nodes &&
          <div>no children</div>
        }
      </div>
    );
  }
}

TreeNode.propTypes = {
  open:PropTypes.bool,
  info:PropTypes.object.isRequired,
  nodes:PropTypes.array,
  actions: PropTypes.object.isRequired
}

动作/NodeActions.js

import { OPEN_NODE, CLOSE_NODE, GET_NODES } from '../constants/NodeActionTypes';

export function openNode() {
  return {
    type: OPEN_NODE
  };
}

export function closeNode() {
  return {
    type: CLOSE_NODE
  };
}


export function getNodes() {
  return {
    type: GET_NODES
  };
}

减速器/TreeNodeReducer.js

import { OPEN_NODE, CLOSE_NODE, GET_NODES } from '../constants/NodeActionTypes';

const initialState = {
  open: false,
  nodes: [],
  info: {}
}

const testNodes = [
  {name:'t1',type:'t1'},
  {name:'t2',type:'t2'},
  {name:'t3',type:'t3'},
]


function getFileList() {
  return {
    nodes: testNodes
  }
}


export default function opener(state = initialState, action) {
  switch (action.type) {
  case OPEN_NODE:
    var {nodes} = getFileList()
    return {
      ...state,
      open:true,
      nodes:nodes
    };
  case CLOSE_NODE:
    return {
      ...state,
      open:false
    };
  case GET_NODES:
    var {nodes} = getFileList()
    return {
      ...state,
      nodes:nodes
    };
  default:
    return state;
  }
}

完整代码见我的githubhttps://github.com/eromoe/simple-redux-boilerplate https://github.com/eromoe/simple-redux-boilerplate

我没有看到涵盖此类组件的示例,并且谷歌结果没有任何帮助。 有什么想法可以克服这个问题吗?

update: 我看到这个如何在reactjs中管理树组件中的状态 https://stackoverflow.com/questions/20503559/how-to-manage-state-in-a-tree-component-in-reactjs

但解决方案是将整个树传递给状态,不能在文件管理器中使用。


我正在使用 React 和 Redux 实现一个类似 Github 的应用程序。

目前,我仅列出存储库并显示其文件以及浏览它们。

我不知道这被认为是好还是坏实践,但这就是我实现 Tree 组件的方式。

在每个树组件内,我都有一个指向其自身的链接。我在路线上传递了一些数据,这样我就可以在渲染时获取下一棵树。

成分

class Tree extends Component {
  constructor(props) {
    super(props);

    this.renderList = this.renderList.bind(this);
  }

  componentWillMount() {
    this.props.getTree(this.props.params.sha);
  }

  componentWillReceiveProps(nextProps) {
    if(nextProps.params.sha !== this.props.params.sha) {
      this.props.getTree(nextProps.params.sha);
    }
  }

  renderList(file) {
    return (
      <tr key={ file.sha }>
        { file.type == 'tree'
       ? <td><Link to={`/repository/${this.props.params.repoName}/tree/${file.path}/${file.sha}`}>{ file.path }</Link></td>
       : <td><Link to={`/repository/${this.props.params.repoName}/blob/${file.sha}/${file.path}`}>{ file.path }</Link></td>}
      </tr>
    )
  }

  render() {
    const treeFile = this.props.tree;
    const fileName = this.props.params.path;

    return (
      <div className="row">
        <h3>{ fileName }</h3>
        <div className="col-md-12">
          <table className="table table-hover table-bordered">
            <tbody>
              { isEmpty(treeFile.tree) ? <tr>Loading</tr> : treeFile.tree.map(this.renderList) }
            </tbody>
          </table>
        </div>
      </div>
    )
  }
}
export default Tree;

Action

const setTree = (tree) => {
  return {
    type: actionTypes.GET_TREE,
    tree
  };
};

export const getTree = (sha) => {

  return (dispatch, getState) => {
    const { repository, profile } = getState();
    const repo = GitHubApi.getRepo(profile.login, repository.name);

    repo.getTree(sha, function(err, data) {
      dispatch(setTree(data));
    });
  }
}

Reducer

const initialState = "";

export const tree = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.GET_TREE:
      return getTree(state, action);
  }
  return state;
}

const getTree = (state, action) => {
  const { tree } = action;
  return tree;
}

完整代码可以查看我的github仓库

https://github.com/glundgren93/Github-redux https://github.com/glundgren93/Github-redux

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在react redux中实现一个自包含组件? 的相关文章

随机推荐

  • DynamicDataDisplay ChartPlotter 删除所有绘图

    在我的 WPF 应用程序中 我有一个 D3 ChartPlotter 可以在其中绘制 4 个折线图 这是 XAML 代码
  • Objective-C 类是否可以在 .h 中实现 swift 协议

    是否有可能Objective C类来实现Swift协议中的 h以便其他Swift类可以参考Objective C类由Swift协议类型 Let MySwiftProtocol be the Swift协议类型 现在假设我有这个 h对于我的班
  • Apache 错误:地址已在使用中:make_sock:无法绑定到地址 [::]:443

    Apache 启动时出错 Address already in use make sock could not bind to address 443 Executing start method lib svc method http a
  • Spring安全和特殊字符

    我需要通过 url 在用户名和 或密码中使用特殊字符使用 j spring security check 登录 http localhost 8080 appname j spring security check j username u
  • 在 R 中解析和评估字符串表达式的列?

    如何将 R 中的一列字符串表达式作为管道的一部分进行解析和求值 在下面的示例中 我生成了所需的列 evaluated 但我知道这不是正确的做法 我尝试采取 tidyverse 方法 但我只是很困惑 library tidyverse df
  • 如何在 Docker SQL Server 映像上运行安装脚本?

    我正在尝试在 Docker SQL Server 映像上运行安装脚本 为此 我从 mssql 映像创建了一个 Dockerfile FROM microsoft mssql server linux 2017 CU8 Create dire
  • 有没有好的 AS3 代码片段/示例的指针?

    我是 AS3 的新手 每天都在学习 我正在寻找好的 AS3 代码片段 示例 小项目 我可以将其用于学习目的和参考 不依赖于 Flash IDE 因为我使用 Flex SDK 和 Flash Develop 此外 我还专门寻找有关音频 视频流
  • jQuery/AJAX - 单击按钮时将内容加载到 div 中?

    有人可以在这里提供帮助吗 我想填充一个div 例如 div div 包含来自外部文件的内容 例如 includes about info html 当单击某个类别的按钮时 例如 p class classloader Click Here
  • 保存实体会导致重复插入到查找数据中

    我使用 EF 4 1 代码优先 来创建我的数据库和对象 Given public class Order public int Id get set public string Name get set public virtual Ord
  • 绕过 InAppBrowser Cordova 插件中的 SSL 错误

    我已在 Cordova 项目中添加了一个 InAppBrowser 插件来访问站点并获取令牌 但是虽然该站点在桌面浏览器中正常打开 但从移动浏览器打开时却出现错误 此外 默认的本机浏览器会在出现 SSL 错误时要求继续 但 Cordova
  • 微软动态 - Web API

    我正在尝试通过 Web API 在 Dynamics 365 实例中创建一个新的 事件 案例 在我的http请求中 我不知道哪个字段是必填的 我尝试仅添加标题 主题和客户 但返回 Http 400 错误 我正在使用 Postman 尝试我的
  • 为什么 console.dir('') 打印“无属性”?

    我的印象是字符串具有属性 例如match 为什么console dir 声称 没有属性 至少在 Google Chrome 中 这是因为 是一个字符串文字 而不是一个实例String 班级 由于属性如match宣布于String proto
  • 双击 Selenium 的 javascript 执行

    有一种方法可以通过执行 javascript 来单击元素 如下所示 JavascriptExecutor driver executeScript arguments 0 click element 我想通过执行 JavaScript 来双
  • 允许在 Google 计算引擎 (GCE) 中使用 WebSocket

    我正在使用计算引擎 GCE 通过 Socket IO Node js 运行我的套接字服务器 它仅适用于轮询 当我尝试使用网络客户端时 我收到以下错误代码 WebSocket connection to ws myapp socket app
  • Swift:Switch 语句失败行为

    目前我有这个 let somePoint 1 0 switch somePoint case 0 0 print origin does not print fallthrough case 0 print y axis prints y
  • 如何将路径图像用户存储到数据库中:Codeigniter

    我正在尝试将不同用户的图片路径上传到数据库中 我对 codeigniter 很陌生 并且阅读了很多教程 但我仍然在挣扎 这是我的控制器 但我什至不知道如何将图像与用户会话链接 这是我的代码 function do upload config
  • 将私有 GitLab 的依赖项与 NPM 结合使用

    我正在尝试从私有 GitLab 实例安装 NPM 依赖项 所以 我有带有基本文件的存储库 我在中添加了这个依赖项package json在我的项目上 node demo package https oauth2
  • 通过ajax请求提交html表单? [复制]

    这个问题在这里已经有答案了 可能的重复 jQuery AJAX 提交表单 https stackoverflow com questions 1960240 jquery ajax submit form 我在页面 A 上有一个表单 而不是
  • 在 Three.js 中渲染具有大量对象的多个场景的最佳方式

    想象一下 您想要绘制两个场景 每个场景都有数百个球体 并提供在这些场景之间切换的功能 做到这一点的最佳方法是什么 目前 一个开关大约需要 4 到 5 秒 因为我要删除 创建和绘制每个开关上的所有球体 下面是在场景切换上运行的代码示例 cle
  • 如何在react redux中实现一个自包含组件?

    我正在基于react redux构建一个文件管理器webui 我的目的是通过这个项目掌握react和redux 如您所知 文件管理器需要一个树浏览器 我想构建一个可以包含它自己并且每个都有自己状态的组件 像下面这样 TreeNode可以包含