Pass custom props to Redux Form Field in TypeScript
Asked Answered
O

3

21

I want to pass custom properties to my Redux-Form-Field. In the documentation it says:

Any custom props passed to Field will be merged into the props object on the same level as the input and meta objects.

But passing a custom prop to the Field component will throw a compile error:

<Field
    name="E-Mail"
    component={MaterialTextField}
    myProp="Test"
/>

Property 'myProp' does not exist on type '(IntrinsicAttributes & IntrinsicClassAttributes> & ...

Inside the props attribute I can only add a predefined set of properties like placeholder or type. Passing another prop will throw this error:

<Field
    name="E-Mail"
    component={MaterialTextField}
    props = {{
        myProps: 'Test'
    }}
/>

Type '{ name: "E-Mail"; component: (props: any) => Element; props: { myProps: string; }; }' is not assignable to type '(IntrinsicAttributes & ...

Is there a possibility to pass custom props to the Field component in TypeScript?

Ozenfant answered 8/9, 2017 at 7:49 Comment(2)
you have redux-form and react-redux-form but those are actually two different frameworks. Which one are you referring to?Inodorous
My bad, I am referring to redux-form.Ozenfant
O
20

After some more experimenting on my side I found a solution to pass custom props:

<Field 
    name="myName"
    props={{
        type: 'text'
    }}
    component={myComponent}
    {...{
        myCustomProps1: 'myCustomProp1',
        myCustomProps2: 'myCustomProp2'
    }}
/>

In myComponent you have your custom props on the root level of your properties:

const myComponent = (props) => {
    return <div>{props.myCustomProp1 + " " props.myCustomProp2}</div>
}
Ozenfant answered 29/9, 2017 at 9:55 Comment(0)
Y
3

To pass custom props to Field component of Redux Form, you need to declare an interface of all the props you want to pass.

interface YourCustomProps {
    myProp1: string;
    myProp2: number;
}

Now, use GenericField from Redux Form to make Field as YourCustomField to which you will be able to pass YourCustomProps

import { Field, GenericField } from 'redux-form';

const YourCustomField = Field as new () => GenericField<YourCustomProps>;

Now you can pass custom props to YourCustomField as declared in the interface.

<YourCustomField
    myProp1="Hi"
    myProp2={123}
    component={MaterialTextField}
/>

This way you can pass anything as custom props such as react components as well! :)

Yangyangtze answered 27/1, 2020 at 17:36 Comment(0)
M
0

I'm not a Typescript user, so I'm not sure how the type definitions work, but I found this thread about type definitions for Redux-form v6. In the end they link to this repository which is supposed to have (if I understand it correctly) updated type definitions.

I guess an alternative would be to switch to vanilla JS for this specific functionality. Or maybe it would be possible to define a function that takes your custom prop and then returns a component ready to take the Redux form props and merge them.

Edit: I've tried to illustrate the basic idea of the last suggestion, a so-called HOC (Higher Order Component), in the included code below.

const inputWithCustomFields = (customFields) => ComponentToGetExtraFields => (props) => {
	const mergedProps = {...props, ...customFields};
	return (<ComponentToGetExtraFields {...mergedProps} />);
};

const ComponentThatNeedsCustomStuff = ({myCustomField1, myCustomField2, ...rest}) => {
	console.log('doing stuff with the custom props',myCustomField1, myCustomField2);
	return (<div><h1>{myCustomField1 + myCustomField2}</h1><input {...rest} /></div>);
}

const Parent = () => {
  const myCustomFields = {
     myCustomField1: "Hello, ", 
     myCustomField2: "world!", 
     value: 'can\'t change me',
     onChange: () => { /* do nothing */ }
   };
  const MergedComponent  = inputWithCustomFields(myCustomFields)(ComponentThatNeedsCustomStuff);
  return (<div>
      <MergedComponent />
    </div>);
};

ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Mucker answered 8/9, 2017 at 8:52 Comment(2)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewRecessive
Fair enough. Can't do much about the the remaining links (too much code/text to copy etc.) but I've added a code example for one part that previously was just vaguely pointing at the contents of a link.Mucker

© 2022 - 2024 — McMap. All rights reserved.