【问题标题】:Counter increment in state not updating状态中的计数器增量未更新
【发布时间】:2019-01-04 22:06:08
【问题描述】:

更大的问题是当我设置它不起作用的状态时。我试图在这里解决问题,但遗憾的是这与我的错误不完全相符。尽管如此,行为及其失败的方式与我的相同。

我有一个计数器在点击时应该更新,这应该会触发我的分页。但是第一次点击没有正确更新。由于计数器不会按原样递增,因此它会抛出下面的 pagination 函数。底部的小提琴将所有内容显示在一起。

这就是我想要的:https://jsfiddle.net/drumgod/n5u2wwjg/262413/ 一个按应递增的计数器。

那个小提琴有效,所以我的问题必须在代码中的其他地方。基本思路是这样的:

1.单击按钮将计数器增加 30

2.counter slices 数组分页

3.项目出现在页面上

问题是:

  1. 调用pagination,计数器不会增加。

  2. pagination 内部的逻辑已关闭。

  3. 项目未显示在页面上。

示例代码:

    //should add 30 to state each time but does not on first click

     countBy30() {
           this.setState((prevState => ({
           counter: prevState.counter + 30
       })))
       return this.state.counter
       }

       //func to do pagination by slicing arr

       paginate(arr) {
    // calling here should add 30 but does not on click
           let count = this.countBy30()
     //slices up array - counter seems to screw up this slicing?
          let sliceStart = count - 30
          let sliceEnd = count
          let chunk = arr.slice(sliceStart, sliceEnd)
          return  chunk
    }

https://jsfiddle.net/drumgod/705t1oc8/55/

在单击按钮Next 30 时,数字确实会在渲染中增加,但在第二次单击之前它不会更改列表。这是因为 pagination 函数中的切片由于某种原因关闭了 30。

(由于小提琴很忙,请直接转到小提琴中的countBy30,因为我认为上面是有效的。)

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    问题在于paginate 假设countBy30 返回新的状态值,但状态是异步更新的,因此countBy30 返回旧值,然后分页使用该值对状态进行其他更改。

    您应该重新编写代码,以便完整地确定您的新状态,然后在单个“setState”调用中设置它(即updatePageState 应该设置chunkCommentscounter)。

    这是一个 jsfiddle 显示这个。

    主要变化是:

    在您的构造函数中添加了以下内容:

    this.updatePageState = this.updatePageState.bind(this);
    

    将您的 then 更改为:

    .then(items => {
                        // filter out undefined
                        let comments = items.filter(obj => obj)
                        console.log('c', comments)
                        // push all comments to state
                        this.setState({
                            fullComments: [...comments]
                        })
                        // paginate comments on load
                        let obj = this.paginate(this.state.fullComments)
                        console.log('original obj', obj)
                        // set first 30 to state
                        this.setState({
                            chunkComments: obj
                        })
                    })
    

    到:

    .then(items => {
                        // filter out undefined
                        let comments = items.filter(obj => obj)
                        console.log('c', comments)
                        // push all comments to state
                        let counterAndChunk = this.paginate(comments);
                        this.setState({
                            fullComments: [...comments],
                            ...counterAndChunk
                        });
                    })
    

    并将 paginageupdatePageState 从:

        paginate(arr) {
        //increment and get current count
            let count = this.countBy30()
            console.log('count', count)
            let sliceStart = count - 30
    /* console.log('start', sliceStart)
     */        let sliceEnd = count
    /* console.log('end', sliceEnd) */
            let chunk = arr.slice(sliceStart, sliceEnd)
            /* console.log('chunk', chunk) */
            return chunk
        }
        updatePageState(arr) {
            let obj = this.paginate(arr)
            //console.log('paginate obj', obj)
            this.setState({
                chunkComments: obj
            })
            //console.log('new state', this.state)
        }
    

    到:

        paginate(arr) {
        //increment and get current count
            let count = this.state.counter + 30;
            console.log('count', count)
            let sliceStart = count - 30
    /* console.log('start', sliceStart)
     */        let sliceEnd = count
    /* console.log('end', sliceEnd) */
            let chunk = arr.slice(sliceStart, sliceEnd)
            /* console.log('chunk', chunk) */
            return {chunkComments: chunk, counter: count};
        }
        updatePageState() {
            let newState = this.paginate(this.state.fullComments)
            //console.log('paginate obj', obj)
            this.setState(newState)
            //console.log('new state', this.state)
        }
    

    并改变:

    <button onClick = {() => {this.updatePageState(this.state.fullComments)}} >
    

    到:

    <button onClick = {this.updatePageState}>
    

    【讨论】:

    • 这里发生了什么? this.setState({ fullComments: [...comments], ...counterAndChunk });
    • 这个答案 def 解决了这里的问题,但不是我的整体问题。我通过 2 个子组件将 chunkComments 向下传递。两者中最低的是一个模板,但它没有接收我作为道具传递的数据,除了挂载。即使当我在父母中注销时数据显然是正确的。我想我需要一种方法来复制它,然后再问另一个问题。谢谢!!
    • this.setState({ fullComments: [...comments], ...counterAndChunk }); 使用的是object spread syntax,相当于this.setState({ fullComments: [...comments], counter: counterAndChunk.counter, chunkComments: counterAndChunk.chunkComments });
    • 知道了。您更详细的解释有助于我了解功能以及正在缩短的内容
    【解决方案2】:

    有两种方法可以实现这种功能。

    您可以决定只使用一个 react 组件来处理计数器和分页。就像我在下面展示的那样。

    export default class PaginationWithCounter extends React.Component {
    
        constructor(props) {
            super(props);
            //initialize counter and data
            this.state = {
                counter: 30,
                data: []
            };
    
            this.incrementCounter = this.incrementCounter.bind(this);
        }
    
        componentDidMount() {
            //make ajax call and load data
        }
    
        //reacts to click events
        incrementCounter() {
            this.setState(prevState => {counter: prevState.counter + 30});
        }
    
        render() {
            const {data, counter} = this.state;
            const page = data.slice(counter - 30, counter); //load up to 30 items
            //render the page and the button
            return (
                <div>
                    <ul>
                        {/**iterate through the page array and display them*/}
                    </ul>
                    <button onClick={this.incrementCounter}>increment{counter}</button>
                </div>
            );
        }
    }
    

    您还可以决定拥有一个分页组件和一个计数器组件。在这种情况下,计数器组件从分页组件接受一个分页回调 prop,只要有点击,它就会调用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多