简体   繁体   English

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

[英].push() does not work in the constructor?

I have an array as such: 我有这样一个数组:

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

I had previously separated odd and even array indexes like this: 我以前曾这样分隔奇偶数组索引:

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

But I would like to move this to the constructor and out of render. 但我想将其移至构造函数而不是渲染。 I have it written like this in a componenetDidMount() : 我在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]]
      });
      }
    };

But it doesn't work. 但这是行不通的。 I'm familiar with the idea that you cannot change the state directly but update it only which is why .push() can't be used but how come the above does not work? 我对不能直接更改状态而只能更新状态的想法很熟悉,这就是为什么不能使用.push()但上面的方法为什么不起作用的原因?

-----EDIT OF REAL CODE----- -----实码编辑-----

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],
    }));

}

You can't set your state successfully since your for loop finishes before you set the state. 由于无法在设置状态之前完成for循环,因此无法成功设置状态。 I don't like for loops for this reason and we generally don't use them but you can do it in this way: 由于这个原因,我不喜欢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> 

Update after comments 评论后更新

Since you are fetching your data, before it finishes again you are trying to set your state. 由于您正在获取数据,因此在再次完成数据之前,您尝试设置状态。 I tried to mimic the situation. 我试图模仿这种情况。 This is just one way of many solutions. 这只是许多解决方案的一种。

 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> 

Second update 第二次更新

I used the fakeRequest to mimic your situation, don't use it. 我使用了fakeRequest来模仿您的情况,请不要使用它。 Your code will probably something like this: 您的代码可能如下所示:

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],
         } ))
})

You shouldn't call this.setState in the constructor. 您不应在构造函数中调用this.setState Instead just set it as the initial state: 而是将其设置为初始状态:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM