Javascript 对此做出反应。道具不要';t更新

Javascript 对此做出反应。道具不要';t更新,javascript,arrays,reactjs,Javascript,Arrays,Reactjs,有人能帮我理解为什么我过滤后这个.props不更新吗 这里是我的代码的精简版本 export default class AutoList extends React.Component { constructor(props) { super(props); this.state = { filterValue: 'all', isHidden: true, autoOptValue: '' } } handleOnC

有人能帮我理解为什么我过滤后这个.props不更新吗

这里是我的代码的精简版本

export default class AutoList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      filterValue: 'all',
      isHidden: true,
      autoOptValue: ''
    }
  }

  handleOnChangeBrand(evt) {
    let selectedValue = evt.target.value;
    this.setState({optionValue: selectedValue});

    let filtered = this.props.autos.filter((auto) => {
      if(auto.brands){
        return auto.brands[0] === selectedValue;
      }
      return false;
    });
    console.log(this.props.auto) // still same number
    console.log(filtered) // less autos. Actual filtered array
  }

   render() {
    let autoDetail = this.props.autos.map(auto => {
      return (
        <Auto
          key={auto.id}
          id={auto.id}
          name={auto.name}
          brands={auto.brands ? auto.brands : false}/>
      );
    });

    return (
      <div>

        <section>
          <select id='autoFilter' className={this.state.isHidden ? 'u-is-hidden' : ''} onChange={this.handleOnChangeBrand.bind(this)} value={this.state.autoOptValue}>
            <option value='brand1'> brand1 </option>
            <option value='brand2'> brand2 </option>
          </select>
        </section>

        <ul>
          {autoDetail}
        </ul>
      </div>
    );
  }
导出默认类AutoList扩展React.Component{
建造师(道具){
超级(道具);
此.state={
filterValue:'所有',
伊希登:没错,
自动选项值:“”
}
}
Handleon品牌(evt){
让selectedValue=evt.target.value;
this.setState({optionValue:selectedValue});
let filtered=this.props.autos.filter((自动)=>{
if(汽车品牌){
返回自动。品牌[0]==所选值;
}
返回false;
});
console.log(this.props.auto)//仍然是相同的数字
console.log(过滤)//更少的autos.real过滤数组
}
render(){
让autoDetail=this.props.autos.map(auto=>{
返回(
);
});
返回(
品牌1
品牌2
    {autoDetail}
); }
基本上我有这个。prop.auto是一个100辆汽车的数组,每个都是一个有品牌的对象(这是另一个数组),每个都有2,3个品牌

我能够过滤,因为
过滤后的
会返回一个包含过滤后的汽车的数组,这些汽车是正确的。
但在此之后,this.props.auto不会更新,UI也不会更新

我做了一些类似的事情,但按品牌对汽车进行了分类,结果很顺利。 我不明白这里有什么不同

  • 过滤器返回一个新的数组。这是因为你手头上仍然有原始数组。这是一件好事的原因有很多,实际上没有什么原因是坏事

  • 道具是不可变的(就像你调用过滤器的数组一样)。不要更改
    Props
    上的成员。也不要更改
    Props
    的成员的成员,或者通常更改
    Props
    的任何子代数据。
    这就是
    state
    存在的原因,因此,如果您必须这样做,您可以将其保存在那里


  • 关于#2,通常情况下,您应该将这些内容提取到越来越高的抽象层中,完全脱离视图数据,只传递准备好显示的完成数据。

    this.props
    在组件中实际上是不可变的,因此您无法更新
    this.props.autos的值
    Array#filter
    也是一个纯函数,因此被过滤的数组不会改变,而是返回一个新的过滤数组。这就是为什么在函数中记录
    filtered
    时会看到过滤数组,但
    This.props.autos
    没有改变

    这个问题的简单答案是在渲染方法中进行过滤-我为false的
    optionValue
    添加了初始状态,并在filter方法中对此进行了检查,如果仍然为false,则不进行过滤

    export default class AutoList extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          filterValue: 'all',
          isHidden: true,
          autoOptValue: '',
          optionValue: false
        }
      }
    
      handleOnChangeBrand(evt) {
        let selectedValue = evt.target.value;
        this.setState({optionValue: selectedValue});
      }
    
      render() {
        const { optionValue } = this.state;
        const autoDetail = this.props.autos
        .filter((auto) => {
          if (!optionValue) return true;
          if(auto.brands){
            return auto.brands[0] === optionValue;
          }
          return false;
        })
        .map(auto => {
          return (
            <Auto
              key={auto.id}
              id={auto.id}
              name={auto.name}
              brands={auto.brands ? auto.brands : false}/>
          );
        });
    
        return (
          <div>
    
            <section>
              <select id='autoFilter' className={this.state.isHidden ? 'u-is-hidden' : ''} onChange={this.handleOnChangeBrand.bind(this)} value={this.state.autoOptValue}>
                <option value='brand1'> brand1 </option>
                <option value='brand2'> brand2 </option>
              </select>
            </section>
    
            <ul>
              {autoDetail}
            </ul>
          </div>
        );
      }
    
    导出默认类AutoList扩展React.Component{
    建造师(道具){
    超级(道具);
    此.state={
    filterValue:'所有',
    伊希登:没错,
    自动选项值:“”,
    选项值:false
    }
    }
    Handleon品牌(evt){
    让selectedValue=evt.target.value;
    this.setState({optionValue:selectedValue});
    }
    render(){
    const{optionValue}=this.state;
    const autoDetail=this.props.autos
    .filter((自动)=>{
    如果(!optionValue)返回true;
    if(汽车品牌){
    返回自动品牌[0]==选项值;
    }
    返回false;
    })
    .map(自动=>{
    返回(
    );
    });
    返回(
    品牌1
    品牌2
    
      {autoDetail}
    ); }
    该方法始终返回一个新的筛选数组,而不更改旧数组:

    filter()方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素

    handleOnChangeBrand
    事件中,您正在创建一个过滤数组,而不影响旧数组,但在React调用第二次渲染时不使用该过滤数组

    下面是一个小示例,说明如何处理此问题:

    1) 让react呈现您的默认
    autos
    prop

    export default class AutoList extends React.Component {
    
      render() {
        const autoDetail = this.props.autos.map(auto => {
          return (
            <Autos ... />
          )
        });
    
        return (
          <ul>
            { autoDetail }
          </ul>
        );
      }
    }
    
    导出默认类AutoList扩展React.Component{
    render(){
    const autoDetail=this.props.autos.map(auto=>{
    返回(
    )
    });
    返回(
    
      {autoDetail}
    ); } }
    2) 添加一个单击处理程序和一个状态值,以保存要通过其进行筛选的值:

    export default class AutoList extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          filter: ''  // this is where we will store what we want to filter by
        }
      };
    
      // All this function will do is update the state which we want to filter by
      // this 'arrow function' auto bind 'this' for us, so we don't have to explicitely set .bind as you were doing before 
      handleOnChangeBrand = (event) => {
        this.setState({
          filter: event.target.value
        })
      };
    
      render() {
        const autoDetail = this.props.autos.map(auto => {
          return (
            <Autos ... />
          )
        });
    
        return (
          <ul>
            { autoDetail }
          </ul>
        );
      }
    }
    
    导出默认类AutoList扩展React.Component{
    建造师(道具){
    超级(道具);
    此.state={
    筛选器:“”//这是存储要根据其进行筛选的内容的位置
    }
    };
    //这个函数所要做的就是更新我们想要过滤的状态
    //这个“箭头函数”为我们自动绑定“this”,所以我们不必像以前那样显式地设置.bind
    handleOnChangeBrand=(事件)=>{
    这是我的国家({
    筛选器:event.target.value
    })
    };
    render(){
    const autoDetail=this.props.autos.map(auto=>{
    返回(
    )
    });
    返回(
    
      {autoDetail}
    ); } }
    3) 最后,我们将使用存储在状态中的值筛选出我们想要的汽车品牌,并使用它来构建我们的阵列

    export default class AutoList extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          filter: ''  // this is where we will store what we want to filter by
        }
      };
    
      getFilteredAutos = () => {
        // if we have no filter, return everything!
        if (this.state.filter === '') {
          return this.props.autos;
        }
    
        // this is returning the newely filtered array, without affecting the old one
        return this.props.autos.filter(auto => {
          if(auto.brands){
            // we're filtering by our saved value
            return auto.brands[0] === this.state.filter;
          }
          return false;
        });
      },
    
      handleOnChangeBrand = (event) => {
        this.setState({
          filter: event.target.value
        })
      };
    
      render() {
        // we're mapping by the filtered results here
        const autoDetail = this.getFilteredAutos().map(auto => {
          return (
            <Autos ... />
          )
        });
    
        return (
          <ul>
            { autoDetail }
          </ul>
        );
      }
    }
    
    导出默认类AutoList扩展React.Component{
    建造师(道具){
    超级(道具);
    此.state={
    筛选器:“”//这是存储要根据其进行筛选的内容的位置
    }
    };
    getFilteredAutos=()=>{
    //如果我们没有过滤器,返回所有内容!
    if(this.state.filter===''){
    返回此.props.autos;
    }
    //这将返回新过滤的数组,而不影响旧数组
    返回t