У меня есть приложение React, которое сильно зависит от redux
, react-redux
и redux-saga
.Я начинаю экспериментировать с React Hooks и хуками useSelector
и useDispatch
в react-redux
, и я столкнулся с вопросом, как по существу написать фабричную функцию для генерации хуков для каждого из моих узлов-избыточников..
В общем, у меня есть редукционный узел для каждой конечной точки API, которую использует мое приложение.В этом приложении есть около 100 уникальных конечных точек, а значит, около 100 узлов-резервистов.Каждый из этих узлов затем соответствует одному state-[node].js
файлу, например state-users.js
и т. Д. Каждый из этих файлов состояния инкапсулирует конечную точку, которую они должны вызвать, запускает саги для обработки жизненного цикла HTTP (запуск, сбой, успех и т. Д.) И т. Д.on.
Со временем я написал код, который абстрагирует большую часть стандартного шаблона в служебные функции, включая функции, которые автоматически генерируют создатели действий, селекторы, редукторы и функцию connect
.Это куча кода, несколько запутанная, но суть выглядит примерно так.Во-первых, я настроил массив объектов, описывающих действия, которые возможны для этого узла-редуктора.Упрощенная версия выглядит следующим образом:
const messages = [
{ action: 'GET', creator: 'get', connect: true },
{ action: 'POST', creator: 'post', connect: true },
{ action: 'CLEAR', creator: 'clear', connect: true },
];
Здесь описывается три действия: get
, post
и clear
, и что они должны быть выставлены в разъеме.У меня есть набор общих редукторов (например, большинство get
редукторов одинаковы для разных узлов), поэтому они предполагаются здесь на основе имени.
Затем я настраиваю список селекторов, например: const selectorKeys = ['data','pending','errors'];
... а затем у меня есть заводская функция, в которую я подаю эти массивы, которая выглядит примерно так:
const { connector } = stateGenerators({
keyword: 'users', //redux node keyword
messages: messages,
selectorKeys: selectorKeys
})
Это упрощенная версия того, как все действительно работает, ноэто суть этого.Опять же, весь приведенный выше код абстрагируется в файл состояния, например state-users.js
.
Затем в моем компоненте класса мне просто нужно импортировать connector
из state-users.js
, например так:
import { connector } from 'state-users';
class Users extends Component {
componentDidMount() {
this.props.get();
}
componentWillUnmount() {
this.props.clear();
}
render () {
const { data } = this.props;
return (
<div>
{data.map()}
</div>
)
}
}
export connector()(Users)
Эта модель иногда становится неуклюжей, но приятно то, что почти весь шаблон редукса абстрагирован в общие файлы, поэтому мои отдельные файлы состояний, по большей части, действительно просты.
Теперь к вопросу: возможно ли сделать что-то вроде этого подхода «фабричной функции» с крючками?До сих пор в своих экспериментах я не понял, как это сделать.Есть две фундаментальные проблемы:
- Во-первых, вы не можете помещать хуки в циклы, поэтому я не могу сделать это:
const selectors = {}
const reduxNodeKeyword = 'users';
['data','pending','errors'].map((selectorKey) => {
selectors[selectorKey] = useSelector((state) => state[keyword].selectorKey);
})
Этот код приводит кэта ошибка: React hook "useSelector" cannot be called inside of a callback.
На практике это означает, что я не могу просто передать массив клавиш выбора, который мне нужен, и затем заставить его плюнуть на мои селекторы.
- Во-вторых, вы не можете помещать крючки в условные выражения.Так как первая идея провалилась, я попробовал другой подход в своей заводской функции, который выглядит примерно так:
if (_.includes(stateSelectors, 'data')) {
result['data'] = useSelector((state) => state[keyword].data);
}
Это приводит к этой ошибке: React hook "useSelector" is called conditionally. React Hooks must be called in the exact same order in every component render
Так что это тоже облом.Но я думаю, что у меня осталось то, что для каждого из моих 100 узлов Redux мне пришлось бы написать свой собственный и подробный крючок для более или менее повторяющегося connect
.
Я знаю, я знаю, хуки должны побуждать меня думать по-другому, но мне все еще нужно получать данные с сервера и предоставлять их компонентам, и мне нужно 100 раз следовать одному и тому же базовому шаблону.Даже если хуки делают мои компоненты более элегантными (как я и ожидал), мысль о том, чтобы написать 100 или около того хуков вручную, каждый с достаточным количеством повторяющихся данных, а не каким-то образом автоматически создавать их, используя какой-то заводской подход, дает мне ульи.
Помощь?
Спасибо!