diff --git a/packages/core/package.json b/packages/core/package.json index 55b13b6..8786536 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,62 +1,62 @@ { - "name": "react-forms-processor", - "version": "0.0.35", - "description": "A forms processor for statically declaring forms with dynamic behaviour", - "main": "dist/index.js", - "scripts": { - "test": "jest", - "glow": "glow", - "glow:watch": "glow --watch", - "start": "webpack-dev-server --mode development", - "transpile": "babel src -d dist --copy-files", - "prepublishOnly": "npm run transpile", - "build": "webpack --mode production", - "dev:watch": "webpack --mode development --watch", - "postbuild": "yarn build:flow", - "build:flow": "../../node_modules/flow-copy-source/bin/flow-copy-source.js --verbose --ignore '**/*{story,test}.js' src dist" - }, - "license": "MIT", - "peerDependencies": { - "react": "^16.4", - "react-dom": "^16.4" - }, - "devDependencies": { - "babel-cli": "^6.26.0", - "babel-core": "^6.26.3", - "babel-jest": "^22.4.3", - "babel-loader": "^7.1.4", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-preset-env": "^1.7.0", - "babel-preset-jest": "^22.4.3", - "babel-preset-react": "^6.24.1", - "chai": "^4.2.0", - "chai-enzyme": "^1.0.0-beta.1", - "css-loader": "^0.28.11", - "enzyme": "^3.7.0", - "enzyme-adapter-react-16.3": "^1.3.0", - "flow-bin": "0.79.1", - "flow-types": "^1.0.0", - "gh-pages": "^1.1.0", - "glow": "^1.1.1", - "html-webpack-plugin": "^3.2.0", - "jest": "^22.4.3", - "react": "^16.4", - "react-dom": "^16.4", - "react-test-renderer": "^16.4", - "regenerator-runtime": "^0.11.1", - "style-loader": "^0.21.0", - "webpack": "^4.8.1", - "webpack-cli": "^2.1.3", - "webpack-dev-server": "^3.1.4" - }, - "dependencies": { - "flow-copy-source": "^2.0.2", - "lodash": "^4.17.10" - }, - "jest": { - "verbose": true, - "bail": false, - "rootDir": "src" - } + "name": "react-forms-processor", + "version": "0.0.35", + "description": "A forms processor for statically declaring forms with dynamic behaviour", + "main": "dist/index.js", + "scripts": { + "test": "jest", + "glow": "glow", + "glow:watch": "glow --watch", + "start": "webpack-dev-server --mode development", + "transpile": "babel src -d dist --copy-files", + "prepublishOnly": "npm run transpile", + "build": "webpack --mode production", + "dev:watch": "webpack --mode development --watch", + "postbuild": "yarn build:flow", + "build:flow": "../../node_modules/flow-copy-source/bin/flow-copy-source.js --verbose --ignore '**/*{story,test}.js' src dist" + }, + "license": "MIT", + "peerDependencies": { + "react": "^16.4", + "react-dom": "^16.4" + }, + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-core": "^6.26.3", + "babel-jest": "^22.4.3", + "babel-loader": "^7.1.4", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-preset-env": "^1.7.0", + "babel-preset-jest": "^22.4.3", + "babel-preset-react": "^6.24.1", + "chai": "^4.2.0", + "chai-enzyme": "^1.0.0-beta.1", + "css-loader": "^0.28.11", + "enzyme": "^3.7.0", + "enzyme-adapter-react-16.3": "^1.3.0", + "flow-bin": "0.79.1", + "flow-types": "^1.0.0", + "gh-pages": "^1.1.0", + "glow": "^1.1.1", + "html-webpack-plugin": "^3.2.0", + "jest": "^22.4.3", + "react": "^16.4", + "react-dom": "^16.4", + "react-test-renderer": "^16.4", + "regenerator-runtime": "^0.11.1", + "style-loader": "^0.21.0", + "webpack": "^4.8.1", + "webpack-cli": "^2.1.3", + "webpack-dev-server": "^3.1.4" + }, + "dependencies": { + "flow-copy-source": "^2.0.2", + "lodash": "^4.17.10" + }, + "jest": { + "verbose": false, + "bail": false, + "rootDir": "src" + } } diff --git a/packages/core/src/components/Form.js b/packages/core/src/components/Form.js index 29e5702..00750e5 100644 --- a/packages/core/src/components/Form.js +++ b/packages/core/src/components/Form.js @@ -33,11 +33,6 @@ const valueHasChanged = ( prevState: FormComponentState ) => nextProps.value && nextProps.value !== prevState.value; -const defaultValueHasChanged = ( - nextProps: FormComponentProps, - prevState: FormComponentState -) => nextProps.value && nextProps.value !== prevState.defaultValue; - const formDisabledStateHasChanged = ( nextProps: FormComponentProps, prevState: FormComponentState @@ -59,8 +54,8 @@ export default class Form extends Component< super(props); this.state = { fields: [], - defaultValue: props.value || {}, - value: props.value || {}, + defaultValue: props.defaultValue || {}, + value: props.value || props.defaultValue || {}, isValid: false, defaultFields: [], disabled: props.disabled || false, @@ -90,17 +85,22 @@ export default class Form extends Component< prevState: FormComponentState ) { const defaultFieldsChange = defaultFieldsHaveChanged(nextProps, prevState); - const defaultValueChange = defaultValueHasChanged(nextProps, prevState); + const valueChange = valueHasChanged(nextProps, prevState); if ( defaultFieldsChange || - valueHasChanged(nextProps, prevState) || + valueChange || formDisabledStateHasChanged(nextProps, prevState) || formTouchedBehaviourHasChanged(nextProps, prevState) ) { - const { fields: fieldsFromState, value: valueFromState } = prevState; + const { + fields: fieldsFromState, + defaultValue: defaultValueFromState, + value: valueFromState + } = prevState; let { defaultFields: defaultFieldsFromProps, + defaultValue: defaultValueFromProps, value: valueFromProps, disabled = false } = nextProps; @@ -111,10 +111,23 @@ export default class Form extends Component< showValidationBeforeTouched = false } = nextProps; - // If a new value has been passed to the Form as a prop then it should take precedence over the last calculated state - const value = valueFromProps || valueFromState || {}; + const value = { + ...defaultValueFromProps, + ...valueFromState, + ...valueFromProps + }; const defaultFields = defaultFieldsFromProps || fieldsFromState; + + // TODO: Don't use the field value if the value prop has changed... + if (!valueChange) { + defaultFields.forEach(field => { + if (field.value) { + value[field.name] = field.value; + } + }); + } + let fields; if (defaultFieldsFromProps && defaultFieldsChange) { fields = registerFields(defaultFieldsFromProps, value); @@ -125,7 +138,7 @@ export default class Form extends Component< // We should reset the touched state of all the fields if the value passed as a prop to the form // changes... - const resetTouchedState = defaultValueChange; + const resetTouchedState = valueChange; const nextState = getNextStateFromFields({ fields, @@ -139,12 +152,13 @@ export default class Form extends Component< return { ...nextState, defaultFields: defaultFieldsFromProps, + defaultValue: defaultValueFromProps || defaultValueFromState, disabled, - showValidationBeforeTouched + showValidationBeforeTouched, + value }; - } else { - return null; } + return null; } onFieldChange(id: string, value: Value) { @@ -158,6 +172,7 @@ export default class Form extends Component< let { fields } = this.state; fields = updateFieldTouchedState(id, true, fields); fields = updateFieldValue(id, value, fields); + const nextState = getNextStateFromFields({ fields, lastFieldUpdated: id, @@ -254,7 +269,7 @@ export default class Form extends Component< } createFormContext() { - const { fields, value, isValid } = this.state; + const { fields, defaultValue, value, isValid } = this.state; const { renderer = defaultRenderer, optionsHandler, @@ -271,6 +286,7 @@ export default class Form extends Component< const context: FormContextData = { fields, isValid, + defaultValue, value, registerField: this.registerField.bind(this), renderer, diff --git a/packages/core/src/components/Form.test.js b/packages/core/src/components/Form.test.js index d7eeb0f..c376961 100644 --- a/packages/core/src/components/Form.test.js +++ b/packages/core/src/components/Form.test.js @@ -31,7 +31,7 @@ describe("Context", () => {