如何从反应组件中提取通用逻辑(但是通用逻辑使用setState)

时间:2018-08-21 12:27:48

标签: javascript reactjs

背景

我正在使用React构建一个应用程序。我已经使用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')} />

通过此操作感觉有些不妥(或者至少有可能导致一些问题),我想知道是否还有其他解决方案?

2 个答案:

答案 0 :(得分:2)

所以我实际上是在我的另一个项目上完成的。我将其视为本地设置状态时redux的reducer和给定状态并被调用并返回整个状态以重新设置的函数。

这使得在不同组件之间进行测试和重用极为容易。您可以找到此open sourced here

我正在执行的项目是一个表,因此,如果我想转到下一组数据,则将执行以下操作。

(我确实简化了此示例)

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

答案 1 :(得分:0)

方法1

constructor

在您的代码中

updateInputValue (prop, event) {
   return { [prop]: event.target.value };
};

方法2

someFunction = (event) => {
   this.setState(updateInputValue('someFieldkey', event))
}

在您的代码中

updateInputValue (theThis, prop, event) {
   theThis.setState({ [prop]: event.target.value });
};

对于方法2,我没有尝试过,但是由于javascript中的所有内容都是通过引用提供的,因此当您在该函数中传递someFunction = (event) => { updateInputValue(this, 'someFieldkey', event)) } 实例并使用它的this方法时,我认为它应该可以工作。