Redux Form converting payload from Number to String on blur - reactjs

I'm trying to isolate why React/Redux/Redux-Form is automatically converting my payload to a string, whenever I focus and blur a input field.
There must be some process that is interfering but I don't know how to troubleshoot.
I've tried using the ReduxDevTools Chrome Extension which basically outputs :
type(pin): "##redux-form/INITIALIZE"
▶meta(pin)
▶payload(pin)
Amount(pin): 2222
type(pin): "##redux-form/FOCUS"
▶meta(pin)
type(pin): "##redux-form/BLUR"
▶meta(pin)
touch(pin): true
payload(pin): "2222.00"

Do you need to use redux-form?
If your data can remain within the context of the component, it should.
Here is one option, provided you don't need your data in the global app state:
import React, { Component } from 'react';
import wrapStateHelpers from 'react-state-helpers';
class Example extends Component {
render() {
const { mut, values: { someNumber } } = this.props;
return (
<input
type='number'
value={someNumber}
onChange={mut('someNumber', parseInt)} />
);
}
}
export default wrapStateHelpers(Example);
This just provides an event handler and wrapping component that manages form state in the component-level-state and then passes that state as the values object in the props to your component.
Note the parseInt passed to mut. Input fields nearly always return a string, and react-state-helpers provides an api for data conversion (second parameter to mut can be any function)
Here is a link to the project / docs, if this

The answer in this case was painfully obvious in retrospect. I was using normalize to format the value using .toFixed(2) which unknown to me, always returns a string.

Related

MultiSelect does not update value when value state changes (PrimeReact UI)

https://www.primefaces.org/primereact/showcase/#/datatable
https://www.primefaces.org/primereact/showcase/#/multiselect
I am using the PrimeReact library to create and customize a Data Table.
My table is dynamic and will build itself based on the data given to it. I am assigning different filters to each column depending on the column's data type, but because there are a variable number of columns I must create the filters dynamically.
To accomplish this I am factoring out the filter logic into a separate class which contain their state and logic.
My issue is that the MultiSelect component I am using as a filter interface does not update its value when it's value's state is updated. After updating the state the value remains null. As the MultiSelect component does not have a reference to the previously selected values I can only choose one value at a time.
I think I am missing some understanding regarding class components, as I usually use functional components. I used a class component in this case so that I could access filterElement from the instantiated DropDownFilter class through DropDownFilter.filterElement() and use as a prop in the Column component.
import React from 'react'
import { MultiSelect } from 'primereact/multiselect';
class DropDownFilter extends React.Component {
constructor(props) {
super(props);
this.multiSelRef = React.createRef();
this.state = {
selectedOptions: [],
}
// Added following two lines trying to fix issue but they did not alter behaviour
this.onOptionsChange = this.onOptionsChange.bind(this)
this.filterElement = this.filterElement.bind(this)
}
onOptionsChange = (e) => {
this.props.dt.current.filter(e.value, this.props.field, 'in');
this.setState({selectedOptions : e.value})
}
filterElement = () => {
return (
<React.Fragment>
<MultiSelect
ref={this.multiSelRef}
value={this.state.selectedOptions} //*** value is null even when selectedOptions has been updated after user chooses option.
// Confirmed by viewing value through multiSelRef
options={this.props.options}
onChange={this.onOptionsChange}
optionLabel="option"
optionValue="option"
className="p-column-filter"
/>
</React.Fragment>
)
}
}
export default DropDownFilter;
I learned the state was not working in this case because I was instantiating the DropDownFilter using the new keyword in when using it. This means it wasnt being mounted to the DOM and could not use state.
I am still having issues regarding implementing the custom columns with filters, but I have posted a new question to handle that scope with my new findings.

Display time from database in React Semantic UI with React Moment

A timestamp string is stored in database like so:
startsAt: 1535705100000
endsAt: 1535708100000
currently there is as a const endTime that should convert the timestamp string into a human-readable, as well as a TimeInput field like this:
import Moment from "react-moment";
..
const endTime = (
<Moment unix format="HH:mm">
{endsAt / 1000}
</Moment>
);
.
..
import { TimeInput } from "semantic-ui-calendar-react";
<TimeInput
..
name="startsAt"
placeholder="00:00"
value={endTime}
..
/>
With that const endTime declared, what is being rendered to the input field is [object Object].
The question is - whether I can use to create a constant at all to be displayed as a value in the TimeInput component.
OR/ALSO - what is the best way to render a readable time from a string in such scenario? Desired output: H:mm
Many thanks in advance!
Take a look at your console. My guess is you are probably also getting a prop-type error for the value prop on your TimeInput component. It is rendering [object Object] because you are passing a React component there instead of a string. So it looks like value does not accept a React component as input.
You are using react-moment as your package to convert time. But it is always going to render some sort of html tag around your string when converting the time displayed. You should instead try using moment instead. The main library will return you an actual string which you can directly pass to your value.
Q: whether I can use to create a constant at all to be displayed as a value in the TimeInput component.
A: Yes you can!
BTW you have messed up types - this is a cause why your example doesn't work correctly.
Let's look on types:
endTime is described as const of type JSX.Element
property value of TimeInput element has type of string
So you are using incompatible types as compatible!
The example of how Moment, moment and TimeInput should be used together:
import "./styles.css";
import moment from "moment";
import Moment from "react-moment";
import { TimeInput } from "semantic-ui-calendar-react";
export default function App() {
const endsAt = 1535708100000;
return (
<div className="App">
<h1>React-moment usage example</h1>
<Moment unix format="HH:mm">
{endsAt / 1000}
</Moment>
<TimeInput
name="startsAt"
placeholder="00:00"
value={moment(endsAt).format("HH:mm")}
onChange={() => {
return;
}}
/>
</div>
);
}
Take a look onto working example here: https://codesandbox.io/s/epic-napier-kc6q6k?file=/src/App.tsx

How to store the information in react component.

When I am asking this question, lots of doubts are coming into my mind. well, first I will give my problem description.
I have component X. and it contains checkboxes and a search box.
while something typed (call it search_query) in search box,
X needed to update the checkboxes which matches the search_query. [note that I got all the values of checkboxes by some api call. and it is done when component created. ]
First doubts I came to my mind is that
store (search_query) and (values of checkboxes) in component state
if the values are more searching takes more time.
is it possible to change the values of props inside the component
or is there any other way to do it ??
Since no code is shared. Assuming you are using plain React ( no Redux, middlewares are used ).
Answering your question:
[1] Is it possible to change the values of props inside the component?
Changing props values inside the component is a bad approach.
"All React components must act like pure functions with respect to their props."
[ref: https://facebook.github.io/react/docs/components-and-props.html#props-are-read-only]
Also, the view doesn't get the update if props values changed within the component.
[2] or is there any other way to do it.
yes ( without mutation inside the component )
using "state" property to hold values & setState to update values.
[3] How to store the information in react component?
Let's rename component X as FilterData,
searchbox ( SearchBox ) & checkboxes (SelectionBox) are two individual components.
// Define state to FilterData
class FilterData extends React.Component {
constructor() {
super()
this.state = {
term: '',
searchResults: []
}
}
....
}
// pass the state values to child components as props
class FilterData extends React.Component {
....
render() {
return (
<div>
<SearchBox term={this.state.term} />
<SelectionBox options={this.state.searchResults} />
</div>
)
}
}
In React App,
data flows top down (unidirectional) and there should be a single source of truth.
SearchBox & SelectionBox are two individual (sibling) components,
SearchBox's state has terms ( which has the search string )
When the user enters input SearchBox will update its state and possible to detect change event and fire ajax and get the response.
How SelectionBox can detect search that had happened, how it can get data.
This is why the state is moved to common ancestor FilterData.
[Ref: https://facebook.github.io/react/docs/lifting-state-up.html]
[Ref: https://facebook.github.io/react/docs/state-and-lifecycle.html#the-data-flows-down]
Code Sample -----------------------------------------------------
Selected values are not saved:
https://codepen.io/sudhnk/pen/NgWgqe?editors=1010
Selected values are saved:
https://codepen.io/sudhnk/pen/JJjyZw?editors=1010

In Typescript, is there any way to typecheck passed-in JSX.Element's?

Consider this simple case:
Client of library:
class ClientComponent extends React.Component<any,any> {
render() {
const myNestedElement = (<LibNestedComponent/>)
return <LibComponent nested={myNestedElement}/>
}
}
Library:
class LibNestedComponent extends React.Component<any,any> {
render() { return <div>nested stuff</div> }
}
interface LibComponentProps { nested: JSX.Element }
class LibComponent extends React.Component<LibComponentProps,any> {
render() {
return <div>{this.props.nested}</div>
}
}
As the author of Lib, I'd like to be able to tell my LibComponent clients, via the LibComponentProps interface, that the passed-in nested prop must be an element of type LibNestedComponent - not just any old j.random element. But AFAICT, there's no way to do this; the Typescript doc even says:
The JSX result type. By default the result of a JSX expression is typed as any. You can customize the type by specifying the JSX.Element
interface. However, it is not possible to retrieve type information
about the element, attributes or children of the JSX from this
interface. It is a black box.
Does anyone have a workaround that achieves this kind of typechecking without too much pain?
(The example is deliberately trivial and is not meant to be a sensible use-case.)
Apart from my comment, I don't know if there is a typescript way to restrict the type of component that client component can pass. But there is a way through which you can determine the type of component that was passed as a prop.
You can check the name of the component which was passed and see which type is it.
if (this.props.nested.type.name === 'LibNestedComponent') {
console.log('A valid component is passed');
} else {
console.log('Invalid component is passed');
}
where nested is the component you passed in the example you provided.
In the below picture you can see the name of the component.
But again, this would be a run-time detection.
You can check the type of this.props.nested using the object
if (this.props.nested.type !== LibNestedComponent) {
throw new Error('Invalid prop passed. Make sure that an instance of LibNestedComponent is passed through the nested prop')
}
The problem with Hardik's answer is that, in case your code gets minified, the value of type.name will change and your code will fail. So you should go for the type property directly instead.

Having services in React application

I'm coming from the angular world where I could extract logic to a service/factory and consume them in my controllers.
I'm trying to understand how can I achieve the same in a React application.
Let's say that I have a component that validates user's password input (it's strength). It's logic is pretty complex hence I don't want to write it in the component it self.
Where should I write this logic? In a store if I'm using flux? Or is there a better option?
The issue becomes extremely simple when you realize that an Angular service is just an object which delivers a set of context-independent methods. It's just the Angular DI mechanism which makes it look more complicated. The DI is useful as it takes care of creating and maintaining instances for you but you don't really need it.
Consider a popular AJAX library named axios (which you've probably heard of):
import axios from "axios";
axios.post(...);
Doesn't it behave as a service? It provides a set of methods responsible for some specific logic and is independent from the main code.
Your example case was about creating an isolated set of methods for validating your inputs (e.g. checking the password strength). Some suggested to put these methods inside the components which for me is clearly an anti-pattern. What if the validation involves making and processing XHR backend calls or doing complex calculations? Would you mix this logic with mouse click handlers and other UI specific stuff? Nonsense. The same with the container/HOC approach. Wrapping your component just for adding a method which will check whether the value has a digit in it? Come on.
I would just create a new file named say 'ValidationService.js' and organize it as follows:
const ValidationService = {
firstValidationMethod: function(value) {
//inspect the value
},
secondValidationMethod: function(value) {
//inspect the value
}
};
export default ValidationService;
Then in your component:
import ValidationService from "./services/ValidationService.js";
...
//inside the component
yourInputChangeHandler(event) {
if(!ValidationService.firstValidationMethod(event.target.value) {
//show a validation warning
return false;
}
//proceed
}
Use this service from anywhere you want. If the validation rules change you need to focus on the ValidationService.js file only.
You may need a more complicated service which depends on other services. In this case your service file may return a class constructor instead of a static object so you can create an instance of the object by yourself in the component. You may also consider implementing a simple singleton for making sure that there is always only one instance of the service object in use across the entire application.
The first answer doesn't reflect the current Container vs Presenter paradigm.
If you need to do something, like validate a password, you'd likely have a function that does it. You'd be passing that function to your reusable view as a prop.
Containers
So, the correct way to do it is to write a ValidatorContainer, which will have that function as a property, and wrap the form in it, passing the right props in to the child. When it comes to your view, your validator container wraps your view and the view consumes the containers logic.
Validation could be all done in the container's properties, but it you're using a 3rd party validator, or any simple validation service, you can use the service as a property of the container component and use it in the container's methods. I've done this for restful components and it works very well.
Providers
If there's a bit more configuration necessary, you can use a Provider/Consumer model. A provider is a high level component that wraps somewhere close to and underneath the top application object (the one you mount) and supplies a part of itself, or a property configured in the top layer, to the context API. I then set my container elements to consume the context.
The parent/child context relations don't have to be near each other, just the child has to be descended in some way. Redux stores and the React Router function in this way. I've used it to provide a root restful context for my rest containers (if I don't provide my own).
(note: the context API is marked experimental in the docs, but I don't think it is any more, considering what's using it).
//An example of a Provider component, takes a preconfigured restful.js
//object and makes it available anywhere in the application
export default class RestfulProvider extends React.Component {
constructor(props){
super(props);
if(!("restful" in props)){
throw Error("Restful service must be provided");
}
}
getChildContext(){
return {
api: this.props.restful
};
}
render() {
return this.props.children;
}
}
RestfulProvider.childContextTypes = {
api: React.PropTypes.object
};
Middleware
A further way I haven't tried, but seen used, is to use middleware in conjunction with Redux. You define your service object outside the application, or at least, higher than the redux store. During store creation, you inject the service into the middleware and the middleware handles any actions that affect the service.
In this way, I could inject my restful.js object into the middleware and replace my container methods with independent actions. I'd still need a container component to provide the actions to the form view layer, but connect() and mapDispatchToProps have me covered there.
The new v4 react-router-redux uses this method to impact the state of the history, for example.
//Example middleware from react-router-redux
//History is our service here and actions change it.
import { CALL_HISTORY_METHOD } from './actions'
/**
* This middleware captures CALL_HISTORY_METHOD actions to redirect to the
* provided history object. This will prevent these actions from reaching your
* reducer or any middleware that comes after this one.
*/
export default function routerMiddleware(history) {
return () => next => action => {
if (action.type !== CALL_HISTORY_METHOD) {
return next(action)
}
const { payload: { method, args } } = action
history[method](...args)
}
}
I needed some formatting logic to be shared across multiple components and as an Angular developer also naturally leaned towards a service.
I shared the logic by putting it in a separate file
function format(input) {
//convert input to output
return output;
}
module.exports = {
format: format
};
and then imported it as a module
import formatter from '../services/formatter.service';
//then in component
render() {
return formatter.format(this.props.data);
}
Keep in mind that the purpose of React is to better couple things that logically should be coupled. If you're designing a complicated "validate password" method, where should it be coupled?
Well you're going to need to use it every time the user needs to input a new password. This could be on the registration screen, a "forgot password" screen, an administrator "reset password for another user" screen, etc.
But in any of those cases, it's always going to be tied to some text input field. So that's where it should be coupled.
Make a very small React component that consists solely of an input field and the associated validation logic. Input that component within all of the forms that might want to have a password input.
It's essentially the same outcome as having a service/factory for the logic, but you're coupling it directly to the input. So you now never need to tell that function where to look for it's validation input, as it is permanently tied together.
Same situation: Having done multiple Angular projects and moving to React, not having a simple way to provide services through DI seems like a missing piece (the particulars of the service aside).
Using context and ES7 decorators we can come close:
https://jaysoo.ca/2015/06/09/react-contexts-and-dependency-injection/
Seems these guys have taken it a step further / in a different direction:
http://blog.wolksoftware.com/dependency-injection-in-react-powered-inversifyjs
Still feels like working against the grain. Will revisit this answer in 6 months time after undertaking a major React project.
EDIT: Back 6 months later with some more React experience. Consider the nature of the logic:
Is it tied (only) to UI? Move it into a component (accepted answer).
Is it tied (only) to state management? Move it into a thunk.
Tied to both? Move to separate file, consume in component through a selector and in thunks.
Some also reach for HOCs for reuse but for me the above covers almost all use cases. Also, consider scaling state management using ducks to keep concerns separate and state UI-centric.
I also came from Angular.js area and the services and factories in React.js are more simple.
You can use plain functions or classes, callback style and event Mobx like me :)
// Here we have Service class > dont forget that in JS class is Function
class HttpService {
constructor() {
this.data = "Hello data from HttpService";
this.getData = this.getData.bind(this);
}
getData() {
return this.data;
}
}
// Making Instance of class > it's object now
const http = new HttpService();
// Here is React Class extended By React
class ReactApp extends React.Component {
state = {
data: ""
};
componentDidMount() {
const data = http.getData();
this.setState({
data: data
});
}
render() {
return <div>{this.state.data}</div>;
}
}
ReactDOM.render(<ReactApp />, 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>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="root"></div>
<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>
</body>
</html>
Here is simple example :
I am from Angular as well and trying out React, as of now, one recommended(?) way seems to be using High-Order Components:
A higher-order component (HOC) is an advanced technique in React for
reusing component logic. HOCs are not part of the React API, per se.
They are a pattern that emerges from React’s compositional nature.
Let's say you have input and textarea and like to apply the same validation logic:
const Input = (props) => (
<input type="text"
style={props.style}
onChange={props.onChange} />
)
const TextArea = (props) => (
<textarea rows="3"
style={props.style}
onChange={props.onChange} >
</textarea>
)
Then write a HOC that does validate and style wrapped component:
function withValidator(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props)
this.validateAndStyle = this.validateAndStyle.bind(this)
this.state = {
style: {}
}
}
validateAndStyle(e) {
const value = e.target.value
const valid = value && value.length > 3 // shared logic here
const style = valid ? {} : { border: '2px solid red' }
console.log(value, valid)
this.setState({
style: style
})
}
render() {
return <WrappedComponent
onChange={this.validateAndStyle}
style={this.state.style}
{...this.props} />
}
}
}
Now those HOCs share the same validating behavior:
const InputWithValidator = withValidator(Input)
const TextAreaWithValidator = withValidator(TextArea)
render((
<div>
<InputWithValidator />
<TextAreaWithValidator />
</div>
), document.getElementById('root'));
I created a simple demo.
Edit: Another demo is using props to pass an array of functions so that you can share logic composed by multiple validating functions across HOCs like:
<InputWithValidator validators={[validator1,validator2]} />
<TextAreaWithValidator validators={[validator1,validator2]} />
Edit2: React 16.8+ provides a new feature, Hook, another nice way to share logic.
const Input = (props) => {
const inputValidation = useInputValidation()
return (
<input type="text"
{...inputValidation} />
)
}
function useInputValidation() {
const [value, setValue] = useState('')
const [style, setStyle] = useState({})
function handleChange(e) {
const value = e.target.value
setValue(value)
const valid = value && value.length > 3 // shared logic here
const style = valid ? {} : { border: '2px solid red' }
console.log(value, valid)
setStyle(style)
}
return {
value,
style,
onChange: handleChange
}
}
https://stackblitz.com/edit/react-shared-validation-logic-using-hook?file=index.js
If you are still looking for a service like Angular, you can try the react-rxbuilder library
You can use #Injectable to register the service, and then you can use useService or CountService.ins to use the service in the component
import { RxService, Injectable, useService } from "react-rxbuilder";
#Injectable()
export class CountService {
static ins: CountService;
count = 0;
inc() {
this.count++;
}
}
export default function App() {
const [s] = useService(CountService);
return (
<div className="App">
<h1>{s.count}</h1>
<button onClick={s.inc}>inc</button>
</div>
);
}
// Finally use `RxService` in your root component
render(<RxService>{() => <App />}</RxService>, document.getElementById("root"));
Precautions
Depends on rxjs and typescript
Cannot use arrow functions in the service
Service is not limited to Angular, even in Angular2+,
Service is just collection of helper functions...
And there are many ways to create them and reuse them across the application...
1) They can be all separated function which are exported from a js file, similar as below:
export const firstFunction = () => {
return "firstFunction";
}
export const secondFunction = () => {
return "secondFunction";
}
//etc
2) We can also use factory method like, with collection of functions... with ES6 it can be a class rather than a function constructor:
class myService {
constructor() {
this._data = null;
}
setMyService(data) {
this._data = data;
}
getMyService() {
return this._data;
}
}
In this case you need make an instance with new key...
const myServiceInstance = new myService();
Also in this case, each instance has it's own life, so be careful if you want to share it across, in that case you should export only the instance you want...
3) If your function and utils not gonna be shared, you can even put them in React component, in this case, just as function in your react component...
class Greeting extends React.Component {
getName() {
return "Alireza Dezfoolian";
}
render() {
return <h1>Hello, {this.getName()}</h1>;
}
}
4) Another way you may handle things, could be using Redux, it's a temporary store for you, so if you have it in your React application, it can help you with many getter setter functions you use... It's like a big store that keep tracks of your states and can share it across your components, so can get rid of many pain for getter setter stuffs we use in the services...
It's always good to do a DRY code and not repeating what needs to be used to make the code reusable and readable, but don't try to follow Angular ways in React app, as mentioned in item 4, using Redux can reduce your need of services and you limit using them for some reuseable helper functions like item 1...
I am in the same boat like you. In the case you mention, I would implement the input validation UI component as a React component.
I agree the implementation of the validation logic itself should (must) not be coupled. Therefore I would put it into a separate JS module.
That is, for logic that should not be coupled use a JS module/class in separate file, and use require/import to de-couple the component from the "service".
This allows for dependency injection and unit testing of the two independently.
In the React world we have two types of logic: Stateful and stateless. Now this is the main concept to grasp when starting with React. That here we update state which should update UI as opposed to Angular's direct updates of dom. The two types of logics are:
That do not depend on state changes, i.e. static logic which doesn't need to re-render something based on state changes. For such cases just create regular js files and import them like a library or helper methods
If you have some code that depends on state and u need to resuse it then two options - hocs and the newer hooks. Hooks are a bit hard to wrap our heads around but basically they would force their parent to rerender if their internal state changes so any stateful logic can be defined and reused in different components, and each hook instance would have its own isolated scope.
It's a little bit of a thinking shift to understand state and declarative components but feel free to ask followup questions in comments
or you can inject the class inheritance "http" into React Component
via props object.
update :
ReactDOM.render(<ReactApp data={app} />, document.getElementById('root'));
Simply edit React Component ReactApp like this:
class ReactApp extends React.Component {
state = {
data: ''
}
render(){
return (
<div>
{this.props.data.getData()}
</div>
)
}
}
It is possible to use export keyword to use functions from file which contains necessary methods.
Let me show an example. Let's say we have a file called someService.ts:
export const foo = (formId: string) => {
// ... the code is omitted for the brevity
}
export const bar = (): Entity[] => [
// ... the code is omitted for the brevity
]
export default {
foo,
bar,
}
Then we can use this service in component like this:
import {
foo,
bar,
} from './someService'
const InnerOrderModal: FC = observer(() => {
const handleFormClick = (value: unknown, item: any) => {
foo(item.key)
bar()
return <></>
}

Resources