首页 > 解决方案 > 如何从 React 组件中提取通用逻辑(但通用逻辑是使用 setState)

问题描述

背景

我正在构建一个带有反应的应用程序。我已经使用 react 2.5 年了,但这是我第一次真正开始测试。因此,我从我的组件中删除了尽可能多的逻辑。其中大部分都非常简单,因为对于大多数逻辑来说,在纯函数中很容易思考。

问题

我发现自己在不同的组件中重用了一种特定的方法,因为它是我的输入字段处理程序。在我第三次复制粘贴它之后,我认为必须有一个更清洁的解决方案。

我的功能

此功能目前以完全相同的方式存在于我的 3 个组件中

/**
 * @description
 * Returns a function that updates the state form
 *
 * @param {String} stateKey - key in the state to update
 * @returns {Function}
 */
@autobind
updateInputValue (prop) {
    return (event) => {
        this.setState({ [prop]: event.target.value });
    }
};

我试过的

我试图将它提取出来并this像变量一样传递给它,它起作用了,但我想知道是否有更清洁的方法来做到这一点。

/**
 * @description
 * Returns a function that updates the state of the filter form
 *
 * @param {Object} componentThis - The components context
 * @param {String} stateKey - key in the state to update
 * @returns {Function}
 */
function updateInputValue (componentThis, stateKey) {
    return (event) => {
        componentThis.setState({ [stateKey]: event.target.value });
    }
}

然后在输入中你只是在做

<Input id="foo"
       value={this.state.foo}
       onChange={updateInputValue(this, 'foo')} />

传递这个感觉是错误的(或者至少有一些破坏性的东西),我想知道这个问题是否有其他解决方案?

标签: javascriptreactjs

解决方案


所以我实际上是在我的另一个项目上做到这一点的。我将其视为在本地设置状态时有一个来自 redux 的 reducer,并且在给定状态并返回整个状态以再次设置时调用一个函数。

这使得跨不同组件的测试和重用变得非常容易。你可以在这里找到这个开源的

我正在做的项目是一个表,所以如果我想转到下一组数据,我会执行以下操作。

(我确实简化了这个例子)

import { nextPage } from '../actions/tableActions'

nextPage() {
    this.setState(currentState => {
        return nextPage({ state: currentState })
    });
};

在我的 tableActions.js 文件中,它看起来像

export const nextPage = ({ state }) => {
    const { currentPage } = state.pagination;

    return changePage({ ...state, currentPage: currentPage + 1 })
};

现在写一个测试就这么简单。

it('should update the currentPage to the next page', () => {
    const given = {
        state: {
            pagination: {
                currentPage: 2,
            },
        }
    };
    const expected = {
        pagination: {
            currentPage: 3,
        },
    };

    expect(actions.nextPage(given)).toEqual(expected);
});

推荐阅读