You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS报错.map is not a function:JSON数组转JSON文件问题

解决React加载外部JSON时出现的.map is not a function错误

嘿,我来帮你搞定这个问题!你遇到的.map is not a function错误,核心原因很简单——你现在只是把JSON文件的路径字符串传给了EmployeeSearch组件的url props,但并没有真正发起请求去加载并解析这个文件里的数组数据,所以employeesJSON其实是个字符串,不是数组,自然调用不了.map方法。咱们一步步来修复:

1. 修复getInitialState的错误定义

你原来的代码里重复定义了两次getInitialState,还在里面直接给this.state赋值,这不符合React的规范。我们需要把所有初始状态合并到一个getInitialState里:

getInitialState: function(){
  return {
    searchString: '',
    orderSelect: '',
    data: [] // 初始化空数组,用来存储加载后的JSON数据
  };
},

2. 用componentDidMount加载外部JSON

React组件挂载完成后,我们可以在componentDidMount生命周期钩子里面发起fetch请求,加载外部JSON文件,并把解析后的数据存入state:

componentDidMount: function() {
  fetch(this.props.url)
    .then(response => response.json()) // 解析JSON响应
    .then(data => {
      this.setState({ data: data }); // 把加载到的数组存入state
    })
    .catch(error => {
      console.error('加载JSON失败:', error); // 处理请求错误
    });
},

3. 在render里使用state中的数据

原来的代码里直接用this.props.url作为数据源,现在我们要改用state里的data数组:

render: function() {
  // 从state获取数据,而不是props.url
  let employeesJSON = [...this.state.data],
      searchString = this.state.searchString.trim().toLowerCase(),
      userCount = employeesJSON.length,
      orderBy = this.state.orderSelect;

  // 剩下的过滤、排序逻辑保持不变...
}

修改后的完整代码

///// // EMPLOYEES COMPONENT /////
const EmployeeSearch = React.createClass({
  getInitialState: function(){
    return {
      searchString: '',
      orderSelect: '',
      data: []
    };
  },
  componentDidMount: function() {
    fetch(this.props.url)
      .then(response => response.json())
      .then(data => {
        this.setState({ data: data });
      })
      .catch(error => {
        console.error('加载员工数据失败:', error);
      });
  },
  handleChange: function(e){
    this.setState({searchString:e.target.value});
  },
  change: function(e){
    this.setState({orderSelect: e.target.value});
  },
  render: function() {
    let employeesJSON = [...this.state.data],
        searchString = this.state.searchString.trim().toLowerCase(),
        userCount = employeesJSON.length,
        orderBy = this.state.orderSelect;

    if(searchString.length > 0){
      employeesJSON = employeesJSON.filter(function(l){
        return ( l.name.toLowerCase().match( searchString ) || l.email.toLowerCase().match( searchString ) || l.job.toLowerCase().match( searchString ) );
      });
      userCount = employeesJSON.length;
    }

    if( orderBy == "asc") {
      employeesJSON.sort(function(a,b){
        return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
      })
    } else if (orderBy == "desc") {
      employeesJSON.sort(function(a,b){
        return a.name.toLowerCase() < b.name.toLowerCase() ? 1 : -1;
      })
    }

    return(
      <div className="main-content">
        <div className="row">
          <div className="col small-12 medium-auto">
            <input type="search" className="form__input" value={this.state.searchString} onChange={this.handleChange} placeholder="Search by name, email & position " />
          </div>
          <div className="col small-12 medium-1">
          </div>
          <div className="col small-12 medium-auto align-right">
            <div className="form__select">
              <select onChange={this.change} defaultValue="" value={this.state.orderSelect}>
                <option value="" disabled>Sort by</option>
                <option value="asc">A-Z</option>
                <option value="desc">Z-A</option>
              </select>
            </div>
          </div>
        </div>
        <p>Contact count: {userCount}</p>
        <div className="card__wrapper row">
          { employeesJSON.map(function(l){
            return(
              <div className="col small-6 medium-4 large-3">
                <div className="card">
                  <div className="card__content">
                    <img src={l.profileImg} alt={l.name} className="card__image" />
                    <h3 className="card__name">{l.name}</h3>
                    <p className="card__email">{l.job}</p>
                    <a href={"mailto:" + l.email} className="button" target="_blank">Send email</a>
                  </div>
                </div>
              </div>
            )
          }) }
        </div>
      </div>
    );
  }
});

///// // PAGE - EMPLOYEES /////
const Employees = () => (
  <div>
    <EmployeeSearch url="../json/employees.json" />
  </div>
)

///// // RENDER APP /////
ReactDOM.render(
  <Employees />,
  document.getElementById('app')
);

另外补充一点:我给排序函数补了? 1 : -1,这样排序逻辑才是正确的(原来的写法返回布尔值,而sort方法需要返回数字来确定排序顺序)。

内容的提问来源于stack exchange,提问作者ltjfansite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:05:11