Как реализовать автономный компонент в React Redux? -- javascript поле с участием reactjs поле с участием components поле с участием redux поле с участием react-redux пол Связанный проблема

How to implement a self contained component in react redux?


3
vote

проблема

русский

Я создаю базу файлового менеджера Webui основы на React Redux (моя цель - это управлять React и Redux через этот проект)

Как вы знаете, файловый менеджер нуждается в Tree Explorer. Я хочу построить компонент, который может содержать его, и у каждого есть самостоятельное состояние. как ниже:

<Код> TreeNode Может содержать детей, которые являются <Код> TreeNode Tool.eч <код> TreeNode Удерживайте его состояние <код> {path, children_nodes, right .....} , <код> children_nodes GOOT от Server, <Код> path передается родителем. Это то, что я представляю. Структура как:

 <код> App: TreeNode --TreeNode ----TreeNode ----TreeNode TreeNode TreeNode --TreeNode TreeNode --TreeNode ----TreeNode ----TreeNode   

Но приходят проблемы сюда, потому что redux <код> connect хранить в корне дерева, весь узел под корнем получают тот же состояние ...

Например, у меня есть <код> OPEN_NODE Action, который является дизайном для запуска <код> getFileList fucntion основы на пути этого узла и установите этот узел <код> TreeNode0 код> TreeNode1 . (Примечание: <код> TreeNode2 не реализовать еще, просто дайте поддельные данные на данный момент) Съемка экрана: Введите описание изображения здесь

Нажмите каждый элемент, но <код> TreeNode3 .

Мой код:

Контейнеры / app.js

 <код> TreeNode4  

Контейнеры / treenode.js

 <код> TreeNode5  

Действия / Nodewacts.js

 <код> TreeNode6  

Редукторы / TREENodeCer.js

 <код> TreeNode7  

Для полного кода см. Мой Github https://github.com/eromoe/simple- Redux-Boilerplate

Я не вижу пример, охватывающий такой компонент, и Google не привлекает ничего полезного. Любая идея, чтобы преодолеть это?

<Сильное> Обновление : Я вижу это Как управлять состоянием в компоненте дерева в rectjs

Но решение проходит все дерево в состояние, не может использовать в файловом менеджере.

Английский оригинал

I am building a file manager webui base on react redux(My purpose is to master react and redux through this project)

As you know, a file manager need a tree explorer.I want to build a component which can contain it self and each has self state. like below:

TreeNode can contain children which are TreeNode too.Each TreeNode hold its state {path, children_nodes, right .....}, children_nodes is get from server, path is passed by parent. That's what I imagine. Struct like:

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

But trouble come here, because redux connect store to the tree root, all node under the root receive same state...

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

Click each element , but states are equal.

My code:

containers/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); 

containers/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 } 

actions/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   }; } 

reducers/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;   } } 

For complete code, see my github https://github.com/eromoe/simple-redux-boilerplate

I don't see an example cover such component, and google result nothing helpful. Any idea to overcome this?

update: I see this How to manage state in a tree component in reactjs

But the solution is pass the whole tree to state, can not use in file manager.

</div
              
 
 

Список ответов

1
 
vote
<Р> Я реализует Github как приложение, с помощью React и 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; }   
<Р> Для полного кода, вы можете проверить мой репозиторий на GitHub <Р> https://github.com/glundgren93/Github-redux
 

I'm implementing a Github like app using React and Redux.

For now, I only list repositories and show its files as well as navigate through them.

I don't know if this is considered a good or bad practice, but this is how I implemented my Tree component.

Inside each Tree Component, I have a Link to itself. And I pass some data on the route, so I'm able to get the next tree when I render it.

App

Component

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; } 

For the complete code, you can check my repository on github

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

</div
 
 
0
 
vote
<Р> Все ваши <код> TreeNode имеет такое же состояние из Redux, потому что ваш <код> mapStateToProps для всех из них одинаковы. <Р> <код> mapStateToProps может принимать <код> ownProps (далее <код> props обернутого компонента) в качестве второго параметра. Вы можете использовать его, чтобы отличить ваш <код> TreeNodes . В вашем случае, <код> path это вариант хороший. <Р> с учетом состояния написания селектор, как этот <код> 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)); }); } } 0 и возврата узлов соответственно. <Р> Вы можете рассмотреть вопрос о чтении через Redux документы первой, особенно это seciont: Http: / /redux.js.org/docs/recipes/ComputingDerivedData.html
 

All of your TreeNode has the same state from redux because your mapStateToProps for all of them are same.

mapStateToProps can take ownProps (the props of the wrapped component) as second parameter. You can use it to distinguish your TreeNodes. In your case, path is a good option.

considering writing a state selector like this getChildrenNodes(state, path) and return the nodes accordingly.

You may want to consider reading through redux docs first, especially this seciont: http://redux.js.org/docs/recipes/ComputingDerivedData.html

</div
 
 

Связанный проблема

0  Нужен React Router Pro, чтобы помочь мне  ( Need a react router pro to help me ) 
Итак, сегодня я играл с маршрутизатором RACT и попытался изменить это Пример . Я хочу достичь этого: . Боковой NAV отображает только имена Когда пол...

0  Ошибка прокладывания слайдера jQuery: ... не удалось конвертировать аргумент JavaScript ARG 0 [NSIDOMHTMLanChorElement.appendChild]  ( Jquery slider throwing error could not convert javascript argument arg 0 ns ) 
Наш сайт Dev Dev имеет ползунок отлично работает здесь: http://allblacks.01dev.co.nz/index.cfm layout = dnahome Однако мы просто поставили сайт Live, и ...

3  Рисование круга с помощью кинетических js  ( Drawing a circle using kinetic js ) 
Я пытаюсь построить очень базовую покраску, используя каркас kinetic JS. Все все идут хорошо, пока не попытался включить функцию формы, которая позволяет поль...

1  Обработка ошибок METEOR для шаблона именования ошибок опечатки  ( Meteor error handling for template naming typo errors ) 
Недавно у меня была ошибка с именем, используемым в файле помощников. Поскольку используемое имя шаблона было недействительным, все мои глобальные помощники п...

3  Angularjs: Как активировать первый ненулевой элемент в Ngrepeat?  ( Angularjs how to activate first non zero item in ngrepeat ) 
для объекта, такого как <код> notification: { "text":0, "image":2, "video":0 } У меня есть <код> ng-repeat ввиду <код> <div ng-repeat="items...

1  Функция валидации угловых JS Возвращает до завершения вызова API для проверки  ( Angular js validation function returns before the api call for validation is com ) 
<код> if (!validate()) { return; }; function validate() { var nameIsValid = ...

0  Почему это работает над сафари и Firefox, но не на хроме?  ( Why is this working on safari and firefox but not on chrome ) 
У меня есть адаптивное меню навигации, он работает следующим образом: при изменении размера окна появляется значок «Гамбургер» (три строки). Нажатие на этот з...

21  Angularjs NG-модель внутри NG-Repeat имеет плохую производительность  ( Angularjs ng model inside ng repeat has poor performance ) 
У меня проблема с производительностью с угловой в следующем сценарии: <код> <div ng-repeat="a in array"> <input ng-model="something"> </div> Я писал к...

12  Синтаксисная ошибка в видом на бритву при прохождении свойств модели в качестве параметров на функцию JavaScript  ( Syntax error in razor view when passing model properties as parameters to javasc ) 
Я получаю <код> Syntax error на каждой запятой (<код> , ) и на последнем кронштейне (<код> ) ) в следующем коде: <код> <script type="text/javascript"> ...

183  Вертикально центрирующее модальное окно Bootstrap  ( Vertically centering bootstrap modal window ) 
Я хотел бы центрировать мою модаль на ViewPort (Middle), я пытался добавить некоторые свойства CSS <код> .modal { position: fixed; top:50%; left:50%; } ...

0  Запустить функцию JavaScript с использованием C #  ( Trigger javascript function using c sharp ) 
Я должен написать класс C #, который получает содержимое HTML-страницы (страница публичная) и запускает функцию JavaScript, которая загружает файл. Моя цель...

0  Попытка вернуть массив объектов для просмотра, получить «10 $ digest () итераций  ( Trying to return array of objects to view get 10 digest iterations reached ) 
Я пытаюсь создать токенизатор, где пользователь вводится в форматную строку, а пользовательский интерфейс дает им предварительный просмотр анализатора. Когда ...

1  jquery адрес плагин  ( Jquery address plugin issue ) 
Я использую плагин jQuery Address, я реализовал плагин на странице списка, когда я нажимаю на одну из ссылок, функция будет вытащить данные, используя AJAX и ...

1  Если для JavaScript в XSLT не работает [дубликат]  ( If greater than javascript into xslt doesnt work ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> Этот вопрос уже есть ответы здесь : ...

11  Rx JS понимает метод подъема  ( Rx js understanding the lift method ) 
Я хочу создать новый оператор, и я нахожу в Документация То, что один из способов сделать что-то подобное: <код> class MyObservable extends Observable { ...

Связанный проблема

0  Нужен React Router Pro, чтобы помочь мне 
0  Ошибка прокладывания слайдера jQuery: ... не удалось конвертировать аргумент JavaScript ARG 0 [NSIDOMHTMLanChorElement.appendChild] 
3  Рисование круга с помощью кинетических js 
1  Обработка ошибок METEOR для шаблона именования ошибок опечатки 
3  Angularjs: Как активировать первый ненулевой элемент в Ngrepeat? 
1  Функция валидации угловых JS Возвращает до завершения вызова API для проверки 
0  Почему это работает над сафари и Firefox, но не на хроме? 
21  Angularjs NG-модель внутри NG-Repeat имеет плохую производительность 
12  Синтаксисная ошибка в видом на бритву при прохождении свойств модели в качестве параметров на функцию JavaScript 
183  Вертикально центрирующее модальное окно Bootstrap 
0  Запустить функцию JavaScript с использованием C # 
0  Попытка вернуть массив объектов для просмотра, получить «10 $ digest () итераций 
1  jquery адрес плагин 
1  Если для JavaScript в XSLT не работает [дубликат] 
11  Rx JS понимает метод подъема