Skip to content

Instantly share code, notes, and snippets.

View jordangarcia's full-sized avatar

Jordan Garcia jordangarcia

View GitHub Profile
import React from 'react';
import { mount } from 'enzyme';
import { toImmutable, Immutable, Store } from 'nuclear-js';
import flux from 'core/flux';
import Form from './index'
describe('jordan react_components/form', function() {
let component;
beforeEach(function() {
});

React Form Abstraction

What problems are we trying to solve?

  1. There is not a generic solution for handling dirty state checking and reverts throughout our codebase.

  2. Validation is a mess, either it's duplicated as inline validation in the "Input" component and in the "Form" component. Other places it exist in the parent component and passed down through props to the "Input", this means our inputs require the parent component to know and do a ton of validation making them no longer easily portable.

import { Button, ButtonRow, Code, Input, Label } from 'optimizely-oui';
import Immutable from 'optly/immutable';
import PropTypes from 'prop-types';
import React from 'react';
import regexUtils from 'optly/utils/regex';
import { toImmutable } from 'nuclear-js';
import { Form } from 'react_components/form';
import CodeSamplePicker from 'bundles/p13n/components/code_sample_picker';
/*
* Form data structure:
* {
* first_name: '',
* address: {
* street_address: '',
* city: '',
* state: '',
* zip_code: '',
* },
import { Button, ButtonRow, Code, Input, Label } from 'optimizely-oui';
import Immutable from 'optly/immutable';
import PropTypes from 'prop-types';
import React from 'react';
import regexUtils from 'optly/utils/regex';
import { toImmutable } from 'nuclear-js';
import VariationFieldRow from './VariationFieldRow'
@Form({

NodeJS Sticky Bucketing

The problem as it exists today is that in order to do sticky bucketing the userProfileService implements two async methods lookup(userId) and save(userProfile). However the implementation of lookup is handled synchronously and thus won’t allow any asynchronous lookups when doing any sort of bucketing decision.

There are many good reasons to want to keep the javascript-sdk synchronous. By making all of the activate calls async we will create a large API breaking change that will force all customers to use an async approach to our SDK, this is bad.

Proposed Solution

Create separate async versions of all bucketing and tracking functions that rely on userProfileService.lookup and suffix them with WithUserProfileService

  • activate -> activateWithUserProfileService
  • getVariation -> getVariationWithUserProfileService
import * as React from 'react'
import * as optimizely from '@optimizely/optimizely-sdk'
import { OptimizelyContext, VariableValue, IOptimizelySDKReactAPI } from './OptimizelyContext'
import { OptimizelyDatafile, DatafileWrapper } from './Datafile';
interface OptimizelyProviderProps {
datafile: OptimizelyDatafile;
sdkOptions: object;
userId: string,
import * as React from 'react'
import * as optimizely from '@optimizely/optimizely-sdk'
import { OptimizelyContext, VariableValue, IOptimizelySDKReactAPI } from './OptimizelyContext'
import { OptimizelyDatafile, DatafileWrapper } from './Datafile';
interface OptimizelyProviderProps {
datafile: OptimizelyDatafile;
sdkOptions: object;
userId: string,
import * as React from 'react'
import * as optimizely from '@optimizely/optimizely-sdk'
import { OptimizelyContextProvider, VariableValue, IOptimizelySDKReactAPI } from './OptimizelyContext'
import { OptimizelyDatafile, DatafileWrapper } from './Datafile';
interface OptimizelyProviderProps {
datafile: OptimizelyDatafile
sdkOptions: object
userId: string
const myFeature = createFeatureInstance('my-feature', {
getComponent(isEnabled, variables) {
return isEnabled
? ExtendedComponent
: StandardComponent
},
fetchData(isEnabled, variables) {
return isEnabled
? getExtendedData()