当前位置: 首页 > 知识库问答 >
问题:

我可以在一次点击中改变100个组件的状态吗?

仲孙俊贤
2023-03-14

我在一个页面上有100个Post组件。每个都有状态isActive。我也在这一页上单独列出了这些文章的标题。如果单击列表中的项目,则我希望将Post组件的状态更改为isActive:true,并将rest组件中的状态更改为isActive:false。

我的Posts组件超过Post组件,所以我应该在Posts组件中迭代所有Post组件,并将change state设置为isActive:false,而不使用当前单击的Post组件?

在这种情况下,这不是太夸张了吗?效率高吗?我使用Redux,所以也许它会有所帮助?

class Posts extends Component {
  state = { 
    isActive: this.props.isActive
  }

  render() {
    return (
      <div>
        {this.props.posts.map((post, index) => 
          <Post isActive={this.state.isActive} key={index} />
        )}
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    posts: state.posts.posts,
    isActive: state.posts.isActive
  }
}

export default connect(mapStateToProps, null)(Posts);

class Post extends Component {
  state = { 
    isActive: this.props.isActive
  }

  onClick = () => {
    this.setState(state => ({
      isActive: !state.isActive
    }));
  }

  render() { 
    return (
      <div className={this.state.isActive ? "show" : ""} onClick={this.onClick}>
        Post
      </div>
    );
  }
}

export default Post;

class List extends Component {

  onClick = () => {
    //here I would like to set isActive:true to current clicked Post and isActive:false to rest of Posts
  }

  render() {
    return (
      <ul>
        {this.props.posts.map((post, index) => 
          <li onClick={this.onClick}>{post.name}</li>
        )}
      </ul>
    );
  }
}

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

export default connect(mapStateToProps, null)(List);

共有2个答案

韦智刚
2023-03-14

您只需存储selectedID(或索引)并使用简单条件,如下所示:

class Posts extends Component {

  render() {
    return (
      <div>
        {this.props.posts.map((post, index) => 
          <Post isActive={this.props.selectedIDX === index} post={post} />
        )}
      </div>
    );
  }
}    

// connect with posts and selectedIDX 


class List extends Component {
  constructor (props) {
    super(props)
    this.onClickHandler = this.onClickHandler.bind(this);
  }

  onClickHandler = (id) => {
    this.props.actionToSetSelectedIDX( id );
  }

  render() {
    return (
      <ul>
        {this.props.posts.map((post, index) => 
          <li onClick={(e, index) => this.onClickHandler(index) }>{post.name}</li>
        )}
      </ul>
    );
  }

 // connect with posts, selectedIDX and actionToSetSelectedIDX
阳福
2023-03-14

这里有一个简单的应用程序,只在一个文件中:)你可以阅读评论,并尝试了解发生了什么。它将让您了解如何在商店中保持状态状态,调度操作并更新状态。

您将看到,PostList组件没有任何状态。它们只是愚蠢的组件。父组件Posts将呈现它们。

您可以在这里看到一个工作示例,fork和play。本例中有单独的目录和文件。我只是把所有的东西都放在一个文件里,以便正确地移动到这里。我不能保证把沙箱放得太久,所以你可能想马上用叉子叉起来:)

附言:这是午夜的乐趣。它可能不包括最佳实践:)

import React from "react";
import ReactDOM from "react-dom";
import { Provider, connect } from "react-redux";
import { createStore, combineReducers } from "redux";

// To use styles in a single file. You can use a .css file to define those
// and use className instead of styles in the Post component

const styles = {
  post: { border: "1px solid gray", marginTop: "-1px" },
  show: { backgroundColor: "silver"}, 
}

// Posts is the parent component. It renders Post and List component by
// mapping the posts.

class Posts extends React.Component {
  // This method changes the status state by passing a post to
  // the action creator

  handleStatus = post => this.props.changeStatus(post);

  // This method maps the posts and renders Post components for each post.
  // We are passing the post and isActive boolean.

  getPosts() {
    return this.props.posts.map(post => {
      // We are getting the isActive by checking the status state
      // if it has our post's id.
      const isActive = this.props.status[post.id];
      return <Post key={post.id} post={post} isActive={isActive} />;
    });
  }

  // This method renders our List items, li's. Again, we are passing the
  // post and our handleStatus method to change the status.

  getList() {
    return this.props.posts.map(post => (
      <List key={post.id} post={post} handleStatus={this.handleStatus} />
    ));
  }

  render() {
    return (
      <div>
        {this.getPosts()}
        <ul>{this.getList()}</ul>
      </div>
    );
  }
}

// Post is a stateless, dumb component. It just renders the post item.

const Post = props => {
  const { id, title } = props.post;
  const { isActive } = props;

  // We check the isActive and if it is true then add a show class.

  let classes = styles.post;
  if (isActive) {
    classes = { ...classes, ...styles.show };
  }

  return (
    <div style={classes}>
      <p>ID: {id} </p>
      <p>Title: {title}</p>
    </div>
  );
};

// List is a stateless, dumb component just renders li's. But, it has
// handleStatus prop. By onClick and using another method, we are
// passing our post back to the parent, to the handleStatus method

const List = props => {
  const { post, handleStatus } = props;
  const changeStatus = () => handleStatus(post);
  return <li onClick={changeStatus}>{post.title}</li>;
};

// We open our state to our component.

const mapStateToProps = state => ({
  posts: state.posts.posts,
  status: state.posts.status,
});

// This is our action creator, takes the post as parameter and
// use it as the payload.

const changeStatus = post => ({
  type: types.CHANGE_STATUS,
  post,
});

// Connecting our component.

const ConnectedPosts = connect(
  mapStateToProps,
  { changeStatus },
)(Posts);

// Just defining our action creator types, avoiding magic strings.   

const types = {
  CHANGE_STATUS: "CHANGE_STATUS",
};

// This is our reducer. We have one posts property and one status in our state.

const initialState = {
  posts: [
    { id: "1", title: "foo" },
    { id: "2", title: "bar" },
    { id: "3", title: "baz" },
  ],
  status: {},
};

// Our reducer takes the post and adds post's id in our status state.
// In the initial state they are all undefined, so not true. In the first
// click, we change to true for each post. If we click again, we change it to
// false without mutating our original state.

const posts = (state = initialState, action) => {
  switch (action.type) {
    case types.CHANGE_STATUS: {
      const {
        post: { id },
      } = action;
      const newStatus = { ...state.status, [id]: !state.status[id] };
      return { ...state, status: newStatus };
    }
    default:
      return state;
  }
};

// Our store.    

const rootReducer = combineReducers({
  posts,
});

const store = createStore(rootReducer);

// Rendering our app.

const rootElement = document.getElementById("root");

ReactDOM.render(
  <Provider store={store}>
    <ConnectedPosts />
  </Provider>,
  rootElement,
);
 类似资料:
  • 本文向大家介绍在react中怎样改变组件状态,以及状态改变的过程是什么?相关面试题,主要包含被问及在react中怎样改变组件状态,以及状态改变的过程是什么?时的应答技巧和注意事项,需要的朋友参考一下 可以从生命周期的角度来答,对于已经挂载的组件,props 传进来后首先会调用componentWillReceiveProps,然后调用shouldComponentUpdate,若shouldCom

  • 我有一个图像元素,我想改变点击。 这项工作: 但我需要的是: 但是,很明显,它不起作用。在CSS中是否有可能有行为(即不使用JavaScript)?

  • 我正在使用USESTEAT钩子,似乎钩子不正常工作。当我单击一个单选按钮时,最初它不会记录任何内容,但在我第二次单击后,它会记录我单击的前一个单选按钮。每次我单击任何按钮,它都会记录我以前单击的按钮。#sideNote:(我导入的'info'是一个对象数组,每个'increct_answers'属性都有一个数组作为值)。下面是我的代码:

  • 我正在尝试在React中构建我的第一个计算器。我的纽扣似乎有问题(我想)。在测试s时,我发现我第一次点击添加按钮不会更新所有setState。相反,第二次单击会正确更新它。 知道它为什么不起作用吗? 我有一个名为“DaInserting”的div,当用户点击任何数字键时会更新,然后当用户点击加法/减法/等时,应该更新,但它没有。它在第二次点击时更新:-检查。 当用户点击加法/减法后,DaInser

  • 问题内容: 以下是HTML。 以下是Javscript 还有一些CSS 我要的是单击适当的按钮后,将Board组件的大小调整为适当的大小。 我已经尝试过这样 但这是行不通的。 问题答案: 您不能像这样设置React组件的状态。并且组件应负责设置自己的状态。 在您的Board组件内部,在componentDidMount中设置事件侦听器。最好的解决方案是让按钮成为React应用程序的一部分,但这超出

  • 本文向大家介绍AngularJs点击状态值改变背景色的实例,包括了AngularJs点击状态值改变背景色的实例的使用技巧和注意事项,需要的朋友参考一下 实例如下: 以上这篇AngularJs点击状态值改变背景色的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。