Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在react redux中实现自包含组件?_Javascript_Reactjs_Components_Redux_React Redux - Fatal编程技术网

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

Javascript 如何在react redux中实现自包含组件?,javascript,reactjs,components,redux,react-redux,Javascript,Reactjs,Components,Redux,React Redux,我正在基于react-redux构建一个文件管理器webui(我的目的是通过这个项目掌握react和redux) 正如您所知,文件管理器需要一个树资源管理器。我想构建一个组件,该组件可以包含它自己,并且每个组件都有自己的状态。如下图所示: TreeNode也可以包含TreeNode的子节点。每个TreeNode保持其状态{path,children\u nodes,right….},子节点从服务器获取,路径由父节点传递。这就是我的想象。 类似结构: App: TreeNode --TreeNod

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

正如您所知,文件管理器需要一个树资源管理器。我想构建一个组件,该组件可以包含它自己,并且每个组件都有自己的状态。如下图所示:

TreeNode
也可以包含
TreeNode
的子节点。每个
TreeNode
保持其状态
{path,children\u nodes,right….}
子节点
从服务器获取,
路径
由父节点传递。这就是我的想象。 类似结构:

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

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

例如,我有一个
OPEN\u节点
操作,它被设计为触发
getFileList函数
基于此节点的路径并设置此节点的
状态。OPEN
true
(注意:
getFileList函数
尚未实现,现在只需提供假数据) 屏幕截图:

单击每个元素,但
状态是相等的

我的代码:

容器/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);
减速器/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;
  }
}
有关完整的代码,请参阅MyGitHub

我没有看到一个例子涵盖这样的组件,谷歌结果没有任何帮助。 有什么办法克服这个问题吗

更新: 我看到了


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

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

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

我不知道这是一个好的还是坏的做法,但这就是我如何实现我的树组件

在每个树组件中,我都有一个指向自身的链接。我在路径上传递了一些数据,这样我就能在渲染下一棵树时得到它

组件

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;
减速器

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上查看我的存储库


所有
TreeNode
的redux状态相同,因为它们的
MapStateTrops
都相同

mapstatetops
可以将
ownProps
(包装组件的
props
)作为第二个参数。您可以使用它来区分
树节点
。在您的情况下,
path
是一个很好的选择

考虑编写这样的状态选择器
getChildrenNodes(state,path)
,并相应地返回节点

<>你可能想先阅读ReDox文档,特别是这个SeiNo:

在ReDux中查看。
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;
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));
    });
  }
}
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;
}