Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create FormName render props component #4038

Merged
merged 5 commits into from
May 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/api/FormName.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# `FormName`

The `FormName` component allows you to get the name of the form in context - the name given to the enclosing `reduxForm` wrapper.
It is a [render props component](https://reactjs.org/docs/render-props.html).
This can be useful for building reusable components that show the status of any form in your app, for example.

## Importing

```javascript
var FormName = require('redux-form').FormName // ES5
```

```javascript
import { FormName } from 'redux-form' // ES6
```

## Props you can pass to `FormName`

### `children : (props: { form: string }) => React.Node` [required]

`FormName` will call this `children` function with the name of the enclosing form, and render whatever this function returns.
18 changes: 18 additions & 0 deletions src/FormName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @flow

import * as React from 'react'
import PropTypes from 'prop-types'
import type {ReactContext} from './types'

export type Props = {
+children: (props: {form: string}) => React.Node,
}

const FormName = ({children}: Props, {_reduxForm}: ReactContext): React.Node => children({form: _reduxForm && _reduxForm.form})
FormName.contextTypes = {
_reduxForm: PropTypes.shape({
form: PropTypes.string.isRequired,
}).isRequired,
}

export default FormName
7 changes: 7 additions & 0 deletions src/FormNameProps.types.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @flow

import * as React from 'react'

export type Props = {
+children: (props: {form: string}) => React.Node,
}
69 changes: 69 additions & 0 deletions src/__tests__/FormName.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* eslint react/no-multi-comp:0 */
import React, { Component } from 'react'
import { findDOMNode } from 'react-dom'
import { Provider } from 'react-redux'
import { combineReducers as plainCombineReducers, createStore } from 'redux'
import { combineReducers as immutableCombineReducers } from 'redux-immutablejs'
import TestUtils from 'react-dom/test-utils'
import createReduxForm from '../createReduxForm'
import createReducer from '../createReducer'
import FormName from '../FormName'
import plain from '../structure/plain'
import plainExpectations from '../structure/plain/__tests__/expectations'
import immutable from '../structure/immutable'
import immutableExpectations from '../structure/immutable/__tests__/expectations'

const describeFormName = (name, structure, combineReducers, setup) => {
const reduxForm = createReduxForm(structure)
const reducer = createReducer(structure)
const { fromJS } = structure
const makeStore = (initial = {}, logger) => {
const reducers = { form: reducer }
if (logger) {
reducers.logger = logger
}
return createStore(combineReducers(reducers), fromJS({ form: initial }))
}

describe(name, () => {
beforeAll(() => {
setup()
})

it('should pass name to child function and render what it returns', () => {
const store = makeStore({
testForm: {
values: {
foo: 42
}
}
})
class TestForm extends Component {
render() {
return (
<form>
<FormName>
{({form}) => <h1>Form name: {form}</h1>}
</FormName>
</form>
)
}
}
const DecoratedTestForm = reduxForm({ form: 'testForm' })(TestForm)
const comp = TestUtils.renderIntoDocument(
<Provider store={store}>
<DecoratedTestForm />
</Provider>
)

expect(findDOMNode(comp).outerHTML).toBe('<form><h1>Form name: testForm</h1></form>')
})
})
}

describeFormName('FormName.plain', plain, plainCombineReducers, () =>
expect.extend(plainExpectations)
)
describeFormName('FormName.immutable', immutable, immutableCombineReducers, () =>
expect.extend(immutableExpectations)
)
1 change: 1 addition & 0 deletions src/immutable.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as defaultShouldValidate } from './defaultShouldValidate'
export { default as defaultShouldError } from './defaultShouldError'
export { default as defaultShouldWarn } from './defaultShouldWarn'
export { default as Form } from './Form'
export { default as FormName } from './FormName'
export { default as FormSection } from './FormSection'
export { default as SubmissionError } from './SubmissionError'
// alias for propTypes
Expand Down
4 changes: 4 additions & 0 deletions src/immutable.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { Params as DefaultShouldErrorParams } from './defaultShouldError'
import type { Params as DefaultShouldWarnParams } from './defaultShouldWarn'
import type { Config as ReduxFormConfig } from './createReduxForm'
import type { Props as _FormProps } from './Form'
import type { Props as _FormNameProps } from './FormName'
import type {
DefaultProps as FormSectionDefaultProps,
Props as _FormSectionProps
Expand Down Expand Up @@ -77,6 +78,7 @@ import type { Actions } from './actions.types'
type StructureMap = Object

export type FormProps = _FormProps
export type FormNameProps = _FormNameProps
export type FormSectionProps = _FormSectionProps
export type FieldProps = _FieldProps
export type FieldArrayProps = _FieldArrayProps
Expand Down Expand Up @@ -115,6 +117,8 @@ declare export var fieldArrayPropTypes: Object

declare export var formPropTypes: Object

declare export var FormName: React.ComponentType<FormNameProps>

declare export var Field: React.ComponentType<FieldInputProps>

declare export var Fields: React.ComponentType<FieldsInputProps>
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as defaultShouldValidate } from './defaultShouldValidate'
export { default as defaultShouldError } from './defaultShouldError'
export { default as defaultShouldWarn } from './defaultShouldWarn'
export { default as Form } from './Form'
export { default as FormName } from './FormName'
export { default as FormSection } from './FormSection'
export { default as SubmissionError } from './SubmissionError'
// alias for propTypes
Expand Down
4 changes: 4 additions & 0 deletions src/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { Params as DefaultShouldErrorParams } from './defaultShouldError'
import type { Params as DefaultShouldWarnParams } from './defaultShouldWarn'
import type { Config as ReduxFormConfig } from './createReduxForm'
import type { Props as _FormProps } from './Form'
import type { Props as _FormNameProps } from './FormName'
import type {
DefaultProps as FormSectionDefaultProps,
Props as FormSectionProps
Expand Down Expand Up @@ -77,6 +78,7 @@ import type {
type StructureMap = Object

export type FormProps = _FormProps
export type FormNameProps = _FormNameProps
export type FieldProps = _FieldProps
export type FieldArrayProps = _FieldArrayProps

Expand Down Expand Up @@ -114,6 +116,8 @@ declare export var fieldArrayPropTypes: Object

declare export var formPropTypes: Object

declare export var FormName: React.ComponentType<FormNameProps>

declare export var Field: React.ComponentType<FieldInputProps>

declare export var Fields: React.ComponentType<FieldsInputProps>
Expand Down
6 changes: 6 additions & 0 deletions src/util/FormNameProps.types.js.flow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @flow
import * as React from 'react'

export type Props = {
children: (form: {name: string}) => React.Node,
}