UNPKG

@react-awesome-query-builder-dev/ui

Version:
142 lines (123 loc) 5.01 kB
import React, { Component, PureComponent } from "react"; import { Utils } from "@react-awesome-query-builder-dev/core"; import PropTypes from "prop-types"; import treeStoreReducer from "../stores/tree"; import context from "../stores/context"; import {createStore} from "redux"; import {Provider} from "react-redux"; import * as actions from "../actions"; import {immutableEqual} from "../utils/stuff"; import {createValidationMemo} from "../utils/validationMemo"; import {liteShouldComponentUpdate, useOnPropsChanged} from "../utils/reactUtils"; import ConnectedQuery from "./Query"; const {defaultRoot} = Utils.DefaultUtils; const {createConfigMemo, extendConfig} = Utils.ConfigUtils; export default class QueryContainer extends Component { static propTypes = { //config conjunctions: PropTypes.object.isRequired, fields: PropTypes.object.isRequired, types: PropTypes.object.isRequired, operators: PropTypes.object.isRequired, widgets: PropTypes.object.isRequired, settings: PropTypes.object.isRequired, ctx: PropTypes.object.isRequired, onChange: PropTypes.func, onInit: PropTypes.func, renderBuilder: PropTypes.func, value: PropTypes.any, //instanceOf(Immutable.Map) }; constructor(props, context) { super(props, context); useOnPropsChanged(this); const { getExtendedConfig, getBasicConfig, clearConfigMemo } = createConfigMemo({ reactIndex: this._reactInternals?.index ?? -1, maxSize: 2, // current and prev canCompile: true, extendConfig, }); this.getMemoizedConfig = getExtendedConfig; this.getBasicConfig = getBasicConfig; this.clearConfigMemo = clearConfigMemo; this.getMemoizedTree = createValidationMemo(); const config = this.getMemoizedConfig(props); const {shouldCreateEmptyGroup} = config.settings; const canAddDefaultRule = !shouldCreateEmptyGroup; // if prop `value` is not provided, can add default/empty rule? const emptyTree = defaultRoot(config, canAddDefaultRule); const sanitizeTree = !!props.value; const tree = props.value || emptyTree; const validatedTree = this.getMemoizedTree(config, tree, undefined, sanitizeTree); const reducer = treeStoreReducer(config, validatedTree, this.getMemoizedTree, this.setLastTree, this.getConfig); const store = createStore(reducer); this.config = config; this.state = { store }; this.QueryWrapper = (pr) => config.settings.renderProvider(pr, config.ctx); } componentWillUnmount() { this.clearConfigMemo(); } setLastTree = (lastTree) => { if (this.prevTree) { this.prevprevTree = this.prevTree; } this.prevTree = lastTree; }; getConfig = () => { return this.config; }; shouldComponentUpdate = liteShouldComponentUpdate(this, { value: (nextValue, prevValue) => { return false; } }); onPropsChanged(nextProps) { // compare configs const prevProps = this.props; const oldConfig = this.config; const nextConfig = this.getMemoizedConfig(nextProps); const isConfigChanged = oldConfig !== nextConfig; // compare trees const storeValue = this.state.store.getState().tree; const isTreeChanged = !immutableEqual(nextProps.value, this.props.value) && !immutableEqual(nextProps.value, storeValue); const currentTree = isTreeChanged ? (nextProps.value || defaultRoot(nextProps)) : storeValue; const isTreeTrulyChanged = isTreeChanged && !immutableEqual(nextProps.value, this.prevTree) && !immutableEqual(nextProps.value, this.prevprevTree); this.sanitizeTree = isTreeTrulyChanged || isConfigChanged; const canUseOldConfig = isConfigChanged && !isTreeChanged; if (isConfigChanged) { if (prevProps.settings.renderProvider !== nextProps.settings.renderProvider) { this.QueryWrapper = (props) => nextConfig.settings.renderProvider(props, nextConfig.ctx); } this.config = nextConfig; } if (isTreeChanged || isConfigChanged) { const validatedTree = this.getMemoizedTree(nextConfig, currentTree, canUseOldConfig ? oldConfig : undefined, this.sanitizeTree); //return Promise.resolve().then(() => { this.state.store.dispatch( actions.tree.setTree(nextConfig, validatedTree) ); //}); } } render() { // `get_children` is deprecated! const {renderBuilder, get_children, onChange, onInit} = this.props; const {store} = this.state; const config = this.config; const QueryWrapper = this.QueryWrapper; return ( <QueryWrapper config={config}> <Provider store={store} context={context}> <ConnectedQuery config={config} getMemoizedTree={this.getMemoizedTree} getBasicConfig={this.getBasicConfig} sanitizeTree={this.sanitizeTree} onChange={onChange} onInit={onInit} renderBuilder={renderBuilder || get_children} /> </Provider> </QueryWrapper> ); } }