diff --git a/README.md b/README.md
index 115af9e..430dcd2 100644
--- a/README.md
+++ b/README.md
@@ -225,14 +225,6 @@ class DogController extends Controller{
Returns a state tree object with the current controller as the root of the tree. The state tree Object is an observable and it is always up to date, just like the controller's state.
-* #### `setStateTree(stateTree: Object)`:
-
-Sets the state tree to the given state tree object. If you are using `setStateTree`, you have to make sure that all the controlled components in your app receive a unique `serialID` via props.
-
-* #### `addOnStateTreeChangeListener(listener: function)`:
-
-Adds a listener for changes in the state tree. On every change to the state tree, the listener will be called with a string json object representing the current state tree, with the current controller as the root.
-
#### Controller Usage example:
```javascript
diff --git a/package.json b/package.json
index 2f274af..b7dc798 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "controllerim",
- "version": "1.64.6",
+ "version": "2.0.0",
"description": "A simple, clean and well structured state management library for react",
"main": "dist/index.js",
"scripts": {
diff --git a/src/AutoIndexManager/AutoIndexManager.js b/src/AutoIndexManager/AutoIndexManager.js
index 7a1ae18..39b3b34 100644
--- a/src/AutoIndexManager/AutoIndexManager.js
+++ b/src/AutoIndexManager/AutoIndexManager.js
@@ -1,5 +1,6 @@
export let shouldUseExperimentalAutoIndexing = false;
-export const useExperimentalSerialization = (value) => shouldUseExperimentalAutoIndexing = value ===undefined ? true: value;
+// export const useExperimentalSerialization = (value) => shouldUseExperimentalAutoIndexing = value ===undefined ? true: value;
+export const useExperimentalSerialization = () => console.warn('experimental indexing currently not supported');
export class AutoIndexManager {
constructor(componentInstance, onIndexChangeCallback) {
@@ -7,7 +8,7 @@ export class AutoIndexManager {
this.totalChildrenCount = 0;
this.currentFreeChildIndex = 0;
this.onIndexChangeCallback = onIndexChangeCallback;
- this.parentIndexManager = this.component.context && this.component.context.autoIndexManager;
+ this.parentIndexManager = this.component.props.controllerimContext && this.component.props.controllerimContext.autoIndexManager;
if (this.parentIndexManager) {
this.increasTotalCountOnParent();
swizzleShouldComponentUpdate(this);
@@ -35,6 +36,7 @@ export class AutoIndexManager {
}
shouldUpdateIndex() {
+ console.log(this.parentIndexManager.totalChildrenCount)
return this.parentIndexManager.currentFreeChildIndex < this.parentIndexManager.totalChildrenCount;
}
diff --git a/src/AutoIndexManager/AutoIndexManager.spec.js b/src/AutoIndexManager/AutoIndexManager.spec.js
index d7388e4..fe37beb 100644
--- a/src/AutoIndexManager/AutoIndexManager.spec.js
+++ b/src/AutoIndexManager/AutoIndexManager.spec.js
@@ -120,7 +120,7 @@ GrandChild.contextTypes = {
};
-describe('IndexChildrenManager', () => {
+describe.skip('IndexChildrenManager', () => {
beforeEach(() => {
indexesArray = [];
grandChildIndexArray = [];
diff --git a/src/Controller/Controller.js b/src/Controller/Controller.js
index 8a18b05..26fb041 100644
--- a/src/Controller/Controller.js
+++ b/src/Controller/Controller.js
@@ -45,7 +45,7 @@ export class Controller {
addStateTreeFunctionality(this, privateScope);
exposeControllerNodeOnComponent(this, privateScope);
- addGetChildContext(privateScope);
+ pushSelfToControllersArray(privateScope);
exposeStateOnScope(this, privateScope);
exposeGetParentControllerOnScope(this, privateScope);
exposeMockStateOnScope(this, privateScope);
@@ -54,17 +54,11 @@ export class Controller {
swizzleComponentWillUnmount(this, privateScope);
}
}
-const addGetChildContext = (privateScope) => {
+const pushSelfToControllersArray = (privateScope) => {
const componentInstance = privateScope.component;
- componentInstance.getChildContext = function () {
- let controllers = [];
- if (componentInstance.context.controllers) {
- controllers = [...this.context.controllers];
- }
- const controllerNode = componentInstance[CONTROLLER_NODE_PROP];
- controllers.push(controllerNode);
- return { controllers, stateTree: privateScope.stateTree.children, autoIndexManager: privateScope.autoIndexManager };
- };
+ const controllerNode = componentInstance[CONTROLLER_NODE_PROP]; //check if we really need this
+ componentInstance.context.controllers.push(controllerNode);
+ componentInstance.props.controllerimContext.autoIndexManager = privateScope.autoIndexManager;
};
// const stateGuard = (internalState) => {
// if (isStateLocked(internalState) && internalState.initialState !== undefined) {
@@ -202,7 +196,7 @@ const exposeGetParentControllerOnScope = (publicScope, privateScope) => {
};
const staticGetParentController = (currentControllerName, component, parentControllerName) => {
- let parentController = component.context.controllers && getControllerFromContext(component.context, parentControllerName);
+ let parentController = component.props.controllerimContext.controllers && getControllerFromContext(component.props.controllerimContext, parentControllerName);
if (!parentController && isTestMod()) {
parentController = getMockedParent(currentControllerName);
}
@@ -271,9 +265,10 @@ const markGetterOnPrivateScope = (privateScope) => {
const swizzleComponentWillUnmount = (publicScope, privateScope) => {
let originalMethod = privateScope.component.componentWillUnmount ? privateScope.component.componentWillUnmount.bind(privateScope.component) : () => { };
privateScope.component.componentWillUnmount = () => {
- if(privateScope.component.context.stateTree){
- const indexToRemove = privateScope.component.context.stateTree.findIndex(child => child === privateScope.stateTree);
- privateScope.component.context.stateTree.splice(indexToRemove, 1);
+ const parentStateTreeChildren = privateScope.component.props.controllerimContext.parentStateTreeChildren;
+ if(parentStateTreeChildren){
+ const indexToRemove = parentStateTreeChildren.findIndex(child => child === privateScope.stateTree);
+ parentStateTreeChildren.splice(indexToRemove, 1);
}
originalMethod();
};
@@ -294,3 +289,6 @@ const extractControllerName = (instance) => {
return instance.constructor.name;
}
};
+
+
+//todo: swizzle component will mount todo all the context related magic.
\ No newline at end of file
diff --git a/src/Controller/Controller.spec.js b/src/Controller/Controller.spec.js
index 035dd41..ee1039e 100644
--- a/src/Controller/Controller.spec.js
+++ b/src/Controller/Controller.spec.js
@@ -7,20 +7,19 @@ import { TestUtils } from '../TestUtils/testUtils';
import {
Parent, ComponentThatForgetToPassThis,
ComponentThatAskForNonExistentParent,
- ComponentThatPutOneStateInsideAnother,
ComponentThatFetchSiblingController,
ComponentThatInitControllerInConstructor,
ParentThatCanHideChild,
BasicStateTree,
ComponentWithSeralizableChild,
- BasicChild,
- ComponentThatOnlyRenderItsChildren,
+ // BasicChild,
+ // ComponentThatOnlyRenderItsChildren,
// SerializableTree,
// ComponentWithMissingSerialID,
// ComplexStateTree
} from './TestComponents';
-const getFakeComponentInstacne = (controllers) => {
+const getFakeComponentInstance = (controllers) => {
controllers = controllers || [];
controllers.forEach(controller => controller.stateTree = {
listenersLinkedList: {
@@ -34,7 +33,7 @@ const getFakeComponentInstacne = (controllers) => {
}
}
}, );
- return { context: { controllers } };
+ return { context: { controllers }, props: {controllerimContext: { controllers: [...controllers] }, controllerimStateTreeNode: {state: {}, children: []}, testModeID: Math.random()} };
};
@@ -52,7 +51,7 @@ describe('Controller', () => {
it('should memoize getting parent controller', () => {
const controllers = [{ name: 'someParent', instance: 'mocekdParentController' }];
- const testController = new Controller(getFakeComponentInstacne(controllers));
+ const testController = new Controller(getFakeComponentInstance(controllers));
expect(testController.getParentController('someParent')).toEqual('mocekdParentController');
controllers[0].instance = 'changedMocked';
//change will not take effect because of memoization:
@@ -60,7 +59,7 @@ describe('Controller', () => {
});
xit('should throw an error when trying to set the state from outside of the contoller', () => {
- const testController = new Controller(getFakeComponentInstacne());
+ const testController = new Controller(getFakeComponentInstance());
testController.state = { FirstChangeAllwaysAllowed: 'change' };
//after state is set for the first time, no changes outside the controller are allowed:
expect(() => testController.state = { bla: 'bla' }).toThrowError('Cannot set state from outside of a controller');
@@ -71,13 +70,13 @@ describe('Controller', () => {
class ControllerWithoutGetName extends Controller{}
const originalConsole = console.warn;
console.warn = jest.fn();
- new ControllerWithoutGetName(getFakeComponentInstacne());
+ new ControllerWithoutGetName(getFakeComponentInstance());
expect(console.warn).toHaveBeenCalledWith(`Warning: controllers must have a static member "controllerName". Please add it to ControllerWithoutGetName`);
console.warn.mockReset();
expect(console.warn).not.toHaveBeenCalled();
class ControllerWithName extends Controller{}
ControllerWithName.controllerName = 'I am a name!';
- new ControllerWithoutGetName(getFakeComponentInstacne());
+ new ControllerWithoutGetName(getFakeComponentInstance());
console.warn = originalConsole;
});
@@ -151,13 +150,13 @@ describe('Controller', () => {
});
it(`should throw an error if trying to save into state other controller's state`, () => {
- const component = mount();
+ const component = mount();
global.Proxy = backupProxy;
expect(() => component.find('[data-hook="mixStates"]').simulate('click')).toThrowError(`Cannot set state with other controller's state.`);
});
it(`should throw an error if trying to save into state other controller's part of state`, () => {
- const component = mount();
+ const component = mount();
global.Proxy = backupProxy;
expect(() => component.find('[data-hook="mixPartOfState"]').simulate('click')).toThrowError(`Cannot set state with other controller's state.`);
});
@@ -608,68 +607,68 @@ describe('Controller', () => {
expect(didUpdate).toHaveBeenCalled();
});
- it('should add children indexes as serialID when activating useExperimentalIndexing()', () => {
- useExperimentalSerialization();
- const component = mount();
- const controller = TestUtils.getControllerOf(component.instance());
- const expectedValue = {
- 'name': 'Acon',
- 'serialID': 'controllerim_root',
- 'state': {
- 'a': 'a'
- },
- 'children': [
- {
- 'serialID': 0,
- 'name': 'Bcon',
- 'state': {
- 'b': 'b'
- },
- 'children': [
- {
- 'serialID': 0,
- 'name': 'Ccon',
- 'state': {
- 'c': 'c'
- },
- 'children': [
-
- ]
- }
- ]
- },
- {
- 'serialID': 1,
- 'name': 'Ccon',
- 'state': {
- 'c': 'c'
- },
- 'children': [
-
- ]
- }
- ]
- };
- expect(controller.getStateTree()).toEqual(expectedValue);
- });
+ // it('should add children indexes as serialID when activating useExperimentalIndexing()', () => {
+ // useExperimentalSerialization();
+ // const component = mount();
+ // const controller = TestUtils.getControllerOf(component.instance());
+ // const expectedValue = {
+ // 'name': 'Acon',
+ // 'serialID': '0',
+ // 'state': {
+ // 'a': 'a'
+ // },
+ // 'children': [
+ // {
+ // 'serialID': 0,
+ // 'name': 'Bcon',
+ // 'state': {
+ // 'b': 'b'
+ // },
+ // 'children': [
+ // {
+ // 'serialID': 0,
+ // 'name': 'Ccon',
+ // 'state': {
+ // 'c': 'c'
+ // },
+ // 'children': [
+
+ // ]
+ // }
+ // ]
+ // },
+ // {
+ // 'serialID': 1,
+ // 'name': 'Ccon',
+ // 'state': {
+ // 'c': 'c'
+ // },
+ // 'children': [
+
+ // ]
+ // }
+ // ]
+ // };
+ // expect(controller.getStateTree()).toEqual(expectedValue);
+ // });
- it('should handle ownerless children correctly when auto indexing', () => {
- useExperimentalSerialization();
- const expectedValue = {
- 'name': 'ComponentWithSeralizableChildController',
- 'serialID': 'controllerim_root',
- 'state': {},
- 'children': [{
- 'name': 'BasicChildController',
- 'serialID': 0,
- 'state': {},
- 'children': []
- }]
- };
- const component = mount();
- const controller = TestUtils.getControllerOf(component.instance());
- expect(controller.getStateTree()).toEqual(expectedValue);
- });
+ // it('should handle ownerless children correctly when auto indexing', () => {
+ // useExperimentalSerialization();
+ // const expectedValue = {
+ // 'name': 'ComponentWithSeralizableChildController',
+ // 'serialID': 'controllerim_root',
+ // 'state': {},
+ // 'children': [{
+ // 'name': 'BasicChildController',
+ // 'serialID': 0,
+ // 'state': {},
+ // 'children': []
+ // }]
+ // };
+ // const component = mount();
+ // const controller = TestUtils.getControllerOf(component.instance());
+ // expect(controller.getStateTree()).toEqual(expectedValue);
+ // });
});
}
});
diff --git a/src/Controller/StateTree.js b/src/Controller/StateTree.js
index 47db065..10cee42 100644
--- a/src/Controller/StateTree.js
+++ b/src/Controller/StateTree.js
@@ -2,9 +2,7 @@
import { shouldUseExperimentalAutoIndexing, AutoIndexManager } from '../AutoIndexManager/AutoIndexManager';
import { immutableProxy } from '../ImmutableProxy/immutableProxy';
-
const ROOT_CONTROLLER_SERIAL_ID = 'controllerim_root';
-
export const addStateTreeFunctionality = (publicScope, privateScope) => {
initStateTree(publicScope, privateScope);
exposeGetStateTreeOnScope(publicScope, privateScope);
@@ -14,21 +12,18 @@ export const addStateTreeFunctionality = (publicScope, privateScope) => {
const initStateTree = (publicScope, privateScope) => {
const serialID = privateScope.component.props && privateScope.component.props.serialID;
- let newstateTreeNode = {
- name: privateScope.controllerName,
- state: {},
- children: []
- };
+ let stateTreeNode = privateScope.component.props.controllerimStateTreeNode;
+ stateTreeNode.name = privateScope.controllerName;
// newstateTreeNode = shallowProxify(newstateTreeNode);
if (serialID !== undefined) {
- newstateTreeNode.serialID = serialID;
+ stateTreeNode.serialID = serialID;
}
- privateScope.stateTree = newstateTreeNode;
- if (privateScope.component.context.stateTree) {
- privateScope.component.context.stateTree.push(newstateTreeNode);
+ privateScope.stateTree = stateTreeNode;
+ if (privateScope.component.props.controllerimContext.parentStateTreeChildren) {
+ privateScope.component.props.controllerimContext.parentStateTreeChildren.push(stateTreeNode);
} else {
- newstateTreeNode.serialID = ROOT_CONTROLLER_SERIAL_ID;
+ stateTreeNode.serialID = ROOT_CONTROLLER_SERIAL_ID;
}
if (shouldUseExperimentalAutoIndexing) {
diff --git a/src/Controller/TestComponents/Child.js b/src/Controller/TestComponents/Child.js
index 16905f1..79e3710 100644
--- a/src/Controller/TestComponents/Child.js
+++ b/src/Controller/TestComponents/Child.js
@@ -21,6 +21,9 @@ export class ChildController extends Controller {
getState(){
return this.state;
}
+ setAnotherState(state) {
+ this.state = state;
+ }
setPartialState(someObj) {
this.state.someObj = someObj;
}
@@ -39,6 +42,8 @@ export const Child = observer(class extends React.Component {
{this.controller.getPropFromParent()}
{this.controller.getChildProp()}