首页 > 解决方案 > 在 reactjs 中使用状态和映射时出错

问题描述

我是新来的反应。我在搜索中获取 github 用户信息。我无法在我的子组件中获取数据。这是我下面的代码。什么问题,我不能使用 this.state.userList.map

class SearchHeader extends Component {
    constructor(props) {
        super(props);
        this.state = {
            errorMessage: '',
            userList: [],
            isOpen: false,
            userName:''

        };
        this.toggle = this.toggle.bind(this);
        this.getUsers = this.getUsers.bind(this);
    }
    toggle() {
        this.setState({
            isOpen: !this.state.isOpen
        });
    }
    // componentWillMount(){
    //     this.getUsers();
    //   }

      getUsers(e) {
        console.log('get users called='+e.target.value);
        fetch('https://api.github.com/search/users?q='+ e.target.value)
        .then(res => res.json())
        .then(
            userList =>{
                this.setState({userList: userList})
                console.log(userList);
            }
        );
      }


    render() {
        return (
            <div>
                <nav className="navbar navbar-expand-lg navbar-light bg-primary  navbar-inner">
                    <div className="collapse navbar-collapse  navbar-inner navb" >

                        <ul className="navbar-nav  bg-light mr-auto">

                            <li className="nav-item dropdown">
                                <a className="nav-link dropdown-toggle auto" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                    Sort
                               </a>
                                <div className="dropdown-menu" aria-labelledby="navbarDropdown">
                                    <a className="dropdown-item" href="#">Sort by Name (ascending)</a>
                                    <a className="dropdown-item" href="#">Sort by Name (descending)</a>
                                    <div className="dropdown-divider"></div>
                                    <a className="dropdown-item" href="#">Sort by Rank (ascending)</a>
                                    <a className="dropdown-item" href="#">Sort by Rank (descending)</a>                                                                 
                                </div>
                            </li>
                        </ul>

                        <form className="form-inline my-2 my-lg-0 auto" onSubmit={this.getUsers}>
                            <div className="form-group">
                                <input className="form-control mr-sm-2" type="Search" placeholder="Search" 
                                aria-label="Search"  
                                id="userName"                                 
                                onKeyUp={this.getUsers} >                 
                                </input>
                            </div>
                        </form>
                    </div>
                </nav>

                <div > 

                    <UserList userList={this.state.userList}/>
                </div>
            </div>
        );
    }
}

export default SearchHeader;

这是我从父组件获取数据的下面的子组件 这是我从父组件获取数据的下面的子组件

class UserList extends Component {
    constructor(props) {
        super(props)
      this.state ={
          users:this.props.userList
      }
    }




    render() {

        return (

            <div className="container-fluid">
                <br />
                {
                    this.state.users.map((user)=>
                    <div className="jumbotron container">
                   {user.login}
                  </div>
                )

                }
            </div>



        );
    }
}

export default UserList;

标签: reactjs

解决方案


您的组件中有几个问题:

  • 不要将父母的状态复制到儿童状态:users:this.props.userList. 直接使用this.props,React 会知道它必须重新渲染孩子
  • 不要依赖当前状态来设置新状态。使用函数 withprevState而不是isOpen: !this.state.isOpen
  • 在将事件值传递给之前复制setStateconst {value} = e.target;
  • 为列表中的每个用户分配唯一键(不是索引!),否则它不会在列表更新时正确重新呈现

所以你的代码看起来像这样:

class SearchHeader extends Component {
    constructor(props) {
        super(props);
        this.state = {
            errorMessage: '',
            userList: [],
            isOpen: false,
            userName:''

        };
    }

    toggle = () => {
        this.setState( (prevState) => ({
            isOpen: !prevState.isOpen
        }));
    }

    getUsers = (e) => {
        const {value} = e.target;
        console.log('get users called='+value);
        fetch('https://api.github.com/search/users?q='+ value)
        ...
    }

}

和:

class UserList extends Component {
    // Use default constructor

    render() {
        const users = this.props.userList.map( (user) => (
            <div className="jumbotron container" key={user.login}>
              {user.login}
            </div>
        ));
        return (
            <div className="container-fluid">
              <br />
              {users}
            </div>
        );
    }
}

推荐阅读