.push()在构造函数中不起作用?

时间:2018-08-14 21:30:28

标签: arrays reactjs

我有一个这样的数组:

product = [
    {
        name: " size one",
        price: 1
      },
      {
        name: "size two",
        price: 2
      },
      ,
      {
        name: "size three",
        price: 3
      }
    ];

我以前曾这样分隔奇偶数组索引:

for (let i=0; i< product.length; i++ ) {
      if (i % 2 === 0 ){
        evenArray.push(product[i])
      } else {
        oddArray.push(product[i])
      }
    };

但是我想将其移至构造函数而不是渲染。 我在componenetDidMount()中这样写:

  for (let i=0; i< this.state.product.length; i++ ) {
      if (i % 2 === 0 ){
        this.setState({
        evenArray: [...this.state.evenArray, this.state.product[i]]
      });
      } else {
        this.setState({
        oddArray: [...this.state.oddArray, this.state.product[i]]
      });
      }
    };

但是它不起作用。我熟悉这样的想法:您不能直接更改状态,而只能对其进行更新,这就是为什么无法使用.push()但上面的方法为什么不起作用的原因?

-----编辑实码-----

componentDidMount() {
  const oauth = OAuth({
    consumer: {
      key: 'XXXXXXXXX',
      secret: 'XXXXXXXXXXX',
    },
    signature_method: 'HMAC-SHA1',
    hash_function(base_string, key) {
      return crypto.createHmac('sha1', key).update(base_string).digest('base64');
    }
  });

  const request_data1 = {
    url: 'http://localhost:8888/wp-json/wc/v2/products/28/variations?per_page=15',
    method: 'GET',
  };

  const request_data2 = {
    url: 'http://localhost:8888/wp-json/wc/v2/products/28/',
    method: 'GET',
  };

  fetch(request_data1.url, {
    method: request_data1.method,
    headers: oauth.toHeader(oauth.authorize(request_data1))
  })
    .then(response => response.json())
    .then(response => {
      this.setState({
         products1: response.reverse()
      })
   })

   fetch(request_data2.url, {
     method: request_data2.method,
     headers: oauth.toHeader(oauth.authorize(request_data2))
   })
     .then(response => response.json())
     .then(response => {
       this.setState({
          products2: response
       })
    })

    const evenArray = [];
    const oddArray = [];
    for (let i = 0; i < this.state.products1.length; i++) {
      if (i % 2 === 0) {
        evenArray.push( this.state.products1[i] );
      } else {
        oddArray.push(this.state.products1[i]);
      }
    };

    this.setState( prevState => ({
        evenArray: [ ...prevState.evenArray, ...evenArray ],
        oddArray: [...prevState.oddArray, ...oddArray],
    }));

}

2 个答案:

答案 0 :(得分:2)

由于for循环在设置状态之前完成,因此无法成功设置状态。由于这个原因,我不喜欢for循环,我们通常不使用它们,但是您可以通过以下方式做到这一点:

class App extends React.Component {
  state = {
    product: [
      {
        name: " size one",
        price: 1
      },
      {
        name: "size two",
        price: 2
      },
      {
        name: "size three",
        price: 3,
      }
    ],
    evenArray: [],
    oddArray: [],
  }

  componentDidMount() {
    const evenArray = [];
    const oddArray = [];
    for (let i = 0; i < this.state.product.length; i++) {
      if (i % 2 === 0) {
        evenArray.push( this.state.product[i] );
      } else {
        oddArray.push(this.state.product[i]);
      }
    };
    
    this.setState( prevState => ({
        evenArray: [ ...prevState.evenArray, ...evenArray ],
        oddArray: [...prevState.oddArray, ...oddArray],
    }));
  }

  render() {
    console.log( this.state );
    return <div>
        Evens: {JSON.stringify(this.state.evenArray)}
        Odds: {JSON.stringify(this.state.oddArray)}
    </div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

评论后更新

由于您正在获取数据,因此在数据再次完成之前,您正在尝试设置状态。我试图模仿这种情况。这只是许多解决方案中的一种。

const product1 = [
  {
    name: " size one",
    price: 1
  },
  {
    name: "size two",
    price: 2
  },
  {
    name: "size three",
    price: 3,
  }
];

const fakeRequest = () => new Promise( resolve =>
  setTimeout( () => resolve( product1 ), 2000 )
);

class App extends React.Component {
  state = {
    product1: [],
    evenArray: [],
    oddArray: [],
  }

  componentDidMount() {
    fakeRequest()
      .then( product1 => {
        const evenArray = product1.filter((el, i) => i % 2 === 0);
        const oddArray = product1.filter((el, i) => i % 2 !== 0);
        this.setState( prevState => ( {
          product1: [ ...prevState.product1, ...product1 ],
          evenArray: [...prevState.evenArray, ...evenArray ],
          oddArray: [...prevState.oddArray, ...oddArray],
        } ))
      })
  }

  render() {
    console.log(this.state);
    return <div>
      { !this.state.product1.length && <p>Waiting for 2 seconds...</p> }
      Evens: {JSON.stringify(this.state.evenArray)}
      Odds: {JSON.stringify(this.state.oddArray)}
    </div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

第二次更新

我使用fakeRequest来模仿您的情况,请勿使用。您的代码可能会像这样:

fetch(request_data1.url, {
    method: request_data1.method,
    headers: oauth.toHeader(oauth.authorize(request_data1))
  })
    .then(response => response.json())
    .then(response => {
         const products1 = response.reverse();
         const evenArray = products1.filter((el, i) => i % 2 === 0);
         const oddArray = products1.filter((el, i) => i % 2 !== 0);
         this.setState( prevState => ( {
              product1: [ ...prevState.products1, ...product1 ],
              evenArray: [...prevState.evenArray, ...evenArray ],
              oddArray: [...prevState.oddArray, ...oddArray],
         } ))
})

答案 1 :(得分:0)

您不应在构造函数中调用this.setState。而是将其设置为初始状态:

constructor(props) {
  super(props);
  this.state = {
    evenArray: evenArray, 
    oddArray: oddArray,
  };
}