在Javascript/React中将函数和变量作为参数传递给map()

4
我希望能够通过每个map函数传递一个名为verified的prop,但我在设置它时遇到了困难。 更新:verified传递给renderContinents可以工作,但是当像这样向renderCountry添加参数时:
  {continent.countries.map(renderCountry(null, verified))}

我的输出为空白。不应该可以工作吗?
更新代码:
  const renderCities = cities => {
    return (
      <div>
        <label>
          <input
              onChange={onChange}
              type="checkbox"/>
        {cities.name}
        </label>
      </div>
    );
  };

  const renderCountries = ({country, verified}) => {
    console.log("came to country");
    return (
      <div className="city-location"> 
        <label>
            <input
              onChange={onChange}
              type="checkbox"/>
          {country.name}
        </label>
        {country.cities.map(renderCities)}
      </div>
    ); 
  };



function onChange(e) {
  console.log('checkbox verified:', (e.target.verified));
}


class AreasComponent extends Component {
      constructor(props) {
        super(props);
        this.state = { 
        };
        this.renderContinents = this.renderContinents.bind(this);
    }

  componentWillMount() {
    this.props.fetchAllAreas(); 
  }

  renderContinents(verified, continent) {
    console.log("came to continent");
      return(
        <div className="continent-location">
          <label>
            <input
              onChange={onChange}
                type="checkbox"/>
             {continent.name}
          </label>

          {continent.countries.map(renderCountries(null, verified))}

        </div>
    )
  } 


  render() { 
    if (!this.props.verified || !this.props.areas) {
      return <div>Loading Areas...</div>
    }
    return(
        <div> 
          {this.props.areas.map(this.renderContinents.bind(this, this.props.verified))}
        </div>
      );
    }
}

function mapDispatchToProps(dispatch){
  return bindActionCreators({ fetchAllAreas, checkArea}, dispatch);
}


function mapStateToProps(state) {
  return { areas: state.areas.all,
           verified:state.areas.verified
  };
}


export default connect(mapStateToProps, mapDispatchToProps)(AreasComponent);

我的另一个问题是onChange(e)函数。它是全局的,所以当我点击任何复选框时都会起作用,但我想让它能够在被点击时接受一个参数并分派checkArea操作,这对我来说意味着它必须被绑定并且也应该作为参数传递。我尝试过这样做:

  {this.props.areas.map(this.renderContinents.bind(this, this.props.verified, this.props.checkArea))} 

但它返回一个空结果。是否可以将函数发送到map()参数中,是否有办法使renderCountry/renderCity与参数一起工作?


这是 https://dev59.com/Xm865IYBdhLWcg3wduaH 的副本。不要让标题欺骗你,它是底层问题的一个红色诱饵,即你立即调用函数,而不是传递要调用的函数。 - zzzzBov
2个回答

5

当你使用 .bind 绑定参数时,这些参数将成为传递给函数的第一个值。当查看 console.log 输出时,您应该已经注意到了。

也就是说,当您执行以下操作时

var bar = foo.bind(this, x, y);
bar(z);

您可以按照以下顺序获取这些值:
function foo(x, y, z) {}

您在函数中调换了参数的顺序:
renderContinent(checked, continent) {
  // ...
}

然而,你可以保留你已有的代码。你不需要将值传递给renderContinents

如果要将其传递给renderContinents等函数,则可以使用.bind或将调用放在另一个函数中:

continent.countries.map(renderCountries.bind(null, verified))
// or
continent.countries.map(country => renderCountries(country, verified))

谢谢!我现在可以渲染大陆了。只有一个快速问题,null参数代表什么?当我使用这段代码来渲染国家时,国家和验证似乎都是null。我已经更新了我的代码,再次感谢! - lost9123193
null表示函数将绑定到的“this”。这就是.bind主要用于的。但是-正如您所看到的-它也可以绑定参数。它可以绑定任意多个参数,但如果要绑定参数,则还需要提供一个“this”。 如果您不关心“this”将是什么,那么null就可以了。 - Norbert

1
事实上,renderCountry/renderCity 调用带有 checkArea 动作的 onChange() 最简单的方法是将它们放在 AreasComponent 内部(即作为成员函数)。这样它们就可以访问 onChangecheckArea
class AreasComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.onChange = this.onChange.bind(this);
    }

    componentWillMount() {
        this.props.fetchAllAreas();
    }

    onChange(e, type) {
        console.log('checkbox verified:', this.props.verified);
        // call checkArea() here with your parameters
        this.props.checkArea(type);
    }

    renderCities(cities) {
        return (
            <div>
                <label>
                    <input
                        onChange={e => this.onChange(e, 'city')}
                        type="checkbox"/>
                    {cities.name}
                </label>
            </div>
        );
    };

    renderCountries(country) {
        console.log("came to country");
        return (
            <div className="city-location">
                <label>
                    <input
                        onChange={e => this.onChange(e, 'country')}
                        type="checkbox"/>
                    {country.name}
                </label>
                {
                    country.cities.map(this.renderCities)
                }
            </div>
        );
    };

    renderContinents(continent) {
        console.log("came to continent");
        return(
            <div className="continent-location">
                <label>
                    <input
                        onChange={e => this.onChange(e, 'continent')}
                        type="checkbox"/>
                    {continent.name}
                </label>
                {
                    continent.countries.map(this.renderCountries)
                }
            </div>
        )
    }

    render() {
        if (!this.props.verified || !this.props.areas) {
            return <div>Loading Areas...</div>
        }
        return(
            <div>
                {
                    this.props.areas.map(this.renderContinents)
                }
            </div>
        );
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({ fetchAllAreas, checkArea}, dispatch);
}


function mapStateToProps(state) {
    return {
        areas: state.areas.all,
        verified: state.areas.verified
    };
}


export default connect(mapStateToProps, mapDispatchToProps)(AreasComponent);

我其实在三天前就解决了这个问题,但现在将其标记为正确答案,因为它非常类似于我最终采用的方法。 - lost9123193

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接