javascript - 在 React 中动态更改列表项

标签 javascript reactjs

这有点困惑,但我一整天都在努力,所以我有点疲惫。

我正在尝试做一些在 JQuery 中需要 20 秒但在 React 中需要花 20 秒的事情 ́_(ツ)_/́

本质上,在我的应用程序中,标签具有与其相关的重要性 (1-9)。很棒的东西。

我有一个列表组,它按重要性顺序返回我的标签:

const TagScreen = ({
    tags
  }) =>
{

 return(
   <ListGroup>
    { tags.sort(function(a,b) {return a.importance < b.importance}).map((tag) =>
      ( <span key={tag.id}>
          <ListGroupItem className='taglist' bsStyle="success"><p>{tag.name}</p>
              <ListItem 
                active={tag.importance} />
          </ListGroupItem>
        </span>
      )
    )}
   </ListGroup>
 )

}

ListItem 是一个(非常)命名不佳的组件(当我完成这个工作时,需要进行大量的重构),但它本质上是一个重要性选择器。它看起来像这样:

const ListItem = ({index, active}) =>
  { 
    var rows = [];
    for (var i = 1; i < 10; i++) {
    var style = '';
    if (active === i) { style = "active" }
      rows.push(<li className={style}><a href='#'>{i}</a></li>)
    }

  return( 

      <ul className="pagination pull-right pagination-sm"> 
        { rows.map((row) => row)}
      </ul> 

    )
  }

再说一遍,我确信这很糟糕,我是一个 React 新手。本质上,我想要的只是将分页元素上的“事件”样式(从标签的当前重要性开始)更改为单击的样式。我已经尝试了很多很多来做到这一点。一旦我有了这个该死的样式来更改 onClick,我将处理服务器的实际 ping 并稍后更改标记的重要性。

感谢您的帮助。

最佳答案

好吧,您需要确保有一个状态来保存更改,因此您需要一个包含状态的容器组件,或者使用像 redux 这样的东西来处理容器属性的状态

之后你可以这样做

const RangeSelector = ({min, max, current, onSelected}) => {
  let items = [];
  for (let i = min; i < max; i++) {
    items.push(<li className={i === current && 'active'} onClick={(...args) => onSelected(i, ...args)}>{i}</li>);
  }
  return <ul>{ items }</ul>;
};

const Tag = props => {
  return <div>
    <h2>{ props.title }<small> ({ props.importance })</small></h2>
    <RangeSelector current={ props.importance } min={1} max={11} onSelected={ (...args) => props.onUpdate( props.id, ...args ) } />
  </div>;
};

class TagContainer extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {
      tags: [
        { id: 0, title: 'C#', importance: 5 },
        { id: 1, title: 'JavaScript', importance: 1 }
      ] };
  }
  updateTag(id, value) {
    this.setState( this.state.tags.reduce( (current, item) => {
      if (item.id === id) {
        item.importance = value;
      }
      current.push( item );
      return current;
    }, [] ) );
  }
  render() {
    return <div>
      <h1>Tags</h1>
      <div className="tag-list">
      { this.state.tags.map( (tag, key) => <Tag onUpdate={(...args) => this.updateTag(...args)} key={tag.id} {...tag} /> ) }
      </div>
    </div>;
  }
}

ReactDOM.render( <TagContainer />, document.querySelector('#app') );
.active { background-color: green; color: white; }
ul { list-style-type: none; display: inline-block; }
ul li { clear: none; display: inline-block; padding: 5px; }
ul li:hover { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

所以上面这个小应用程序的细节如下:

  • 1 个容器组件,名为 TagContainer

它保存标签的状态,并在子组件发生更改时更新其状态。它以初始状态开始,您可以在构造函数中看到该状态:

constructor(...args) {
  super(...args);
  this.state = {
    tags: [
      { id: 0, title: 'C#', importance: 5 },
      { id: 1, title: 'JavaScript', importance: 1 }
    ] };
}

这意味着,我将有 2 个标签,一个使用 C#,一个使用 JavaScript,重要性分别为 5 和 1

在渲染容器组件期间,它会渲染一个名为 Tag 的无状态组件,并在其 props 上插入一个更新函数,您可以在此处看到:

<Tag onUpdate={(...args) => this.updateTag(...args)} key={tag.id} {...tag} />

这表明,当调用 onUpdate 时,它将把更新转发给 this.updateTag() 函数,该函数将更新状态。发送的所有参数也将转发到该函数。箭头函数确保 this 的上下文引用当前 TagContainer 实例。

更新状态是通过 this.setState() 函数完成的,您可以在其中发送更新后的状态,以便 React 可以重新渲染容器组件。

现在这可能看起来过于复杂,而且可能确实如此,但它将重新创建状态中的标签数组,并更新要更改的一个状态

this.setState( this.state.tags.reduce( (current, item) => {
  if (item.id === id) {
    item.importance = value;
  }
  current.push( item );
  return current;
}, [] ) );

idvalue 通过上面定义的 2 个无状态组件传入。

  • 2 个无状态组件,RangeSelectorTag

RangeSelector 只负责显示某个范围内的可用值,并为当前选定的元素设置事件类。当它被点击时,它将通过从 Tag 组件接收到的 onSelected 方法发送值。

Tag 组件负责显示当前标签,并呈现标题和RangeSelector。它从 TagContainer 组件接收一个 onUpdate 方法,当它被 RangeSelector 调用时,它会添加 1 个额外参数并将其转发到 TagContainer 组件。

最后,状态发生变化,react 将重新渲染您的应用程序,从而导致 DOM 的更新(因为虚拟 dom 和真实 DOM 之间存在差异)

关于javascript - 在 React 中动态更改列表项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46916029/

相关文章:

JavaScript 验证和重定向不起作用

javascript - 使用 HTTP 身份验证自动登录的 GreaseMonkey 脚本

javascript - 打印object标签的url加载的页面

javascript - 如何在 React 中插入具有多个外键的表?

javascript - Wow JS 在页面加载时隐藏元素

javascript - 将函数作为参数传递不起作用

javascript - 在按钮上单击带有确认警报框,取消时也提交查询

reactjs - 打开Modal后如何从Modal顶部显示? ( Ant 设计)

javascript - 如何将 ReactJS es6 代码导入 Express 应用程序?

reactjs - 如何从 react-dropzone 中删除文件?