How to Focus on Errors in react-admin 4.x - react-admin

I've been porting a react-admin 3.19 project for a while now, and the only behavior left to implement on 4.x is to focus the first field that fails validation, in react-admin 3.19 that was achieved with something like:
import createDecorator from 'final-form-focus';
const focusOnErrors = createDecorator();
...
<Edit>
<SimpleForm
decorators={[focusOnErrors]}>
But on 4.x final-form-focus was replaced with react-hook-form, which I found how to focus on the first field with errors, but I'm not sure how to implement that on react-admin or if it will work with react-admin, the code should be something like:
const {
setFocus,
formState: { errors },
} = useForm();
useEffect(() => {
const firstError = Object.keys(errors).reduce(
(field, a) => (errors[field] ? field : a),
null,
);
if (firstError) {
setFocus(firstError);
}
}, [errors, setFocus]);
How can I make react-admin focus on the first field that fails validation?

Related

Populte WYSIWYG editor after react native fetch

I am trying to incorporate this WYSIWYG package into my react native project (0.64.3). I built my project with a managed workflow via Expo (~44.0.0).
The problem I am noticing is that the editor will sometimes render with the text from my database and sometimes render without it.
Here is a snippet of the function that retrieves the information from firebase.
const [note, setNote] = useState("");
const getNote = () => {
const myDoc = doc(db,"/users/" + user.uid + "/Destinations/Trip-" + trip.tripID + '/itinerary/' + date);
getDoc(myDoc)
.then(data => {
setNote(data.data()[date]);
}).catch();
}
The above code and the editor component are nested within a large function
export default function ItineraryScreen({route}) {
// functions
return (
<RichEditor
onChange={newText => {
setNote(newText)
}}
scrollEnabled={false}
ref={text}
initialFocus={false}
placeholder={'What are you planning to do this day?'}
initialContentHTML={note}
/>
)
}
Here is what it should look like with the text rendered (screenshot of simulator):
But this is what I get most of the time (screenshot from physical device):
My assumption is that there is a very slight delay between when the data for the text editor is actually available vs. when the editor is being rendered. I believe my simulator renders correctly because it is able to process the getNote() function faster.
what I have tried is using a setTimeOut function to the display of the parent View but it does not address the issue.
What do you recommend?
I believe I have solved the issue. I needed to parse the response better before assigning a value to note and only show the editor and toolbar once a value was established.
Before firebase gets queried, I assigned a null value to note
const [note, setNote] = useState(null);
Below, I will always assign value to note regardless of the outcome.
if(data.data() !== undefined){
setNote(data.data()[date]);
} else {
setNote("");
}
The last step was to only show the editor once note no longer had a null value.
{
note !== null &&
<RichToolbar
style={{backgroundColor:"white", width:"114%", flex:1, position:"absolute", left:0, zIndex:4, bottom: (toolbarVisible) ? keyboardHeight * 1.11 : 0 , marginBottom:-40, display: toolbarVisible ? "flex" : "none"}}
editor={text}
actions={[ actions.undo, actions.setBold, actions.setItalic, actions.setUnderline,actions.insertLink, actions.insertBulletsList, actions.insertOrderedList, actions.keyboard ]}
iconMap={{ [actions.heading1]: ({tintColor}) => (<Text style={[{color: tintColor}]}>H1</Text>), }}
/>
<RichEditor
disabled={disableEditor}
initialFocus={false}
onChange={ descriptionText => { setNote(descriptionText) }}
scrollEnabled={true}
ref={text}
placeholder={'What are you planning to do?'}
initialContentHTML={note}
/>
}
It is working properly.

How to use remove() (Firebase SDK 9 web)

How to use "remove()" in SDK v9 web?
(context: I'm learning React Native (using Expo) and there's this todo app).
There are no examples in the documentation. Here is what I have:
// firebase
import app from "./firebaseConfig";
import {
getDatabase,
ref,
set,
push,
onValue,
remove,
child,
} from "firebase/database";
// etc
const db = getDatabase(app);
const taskListRef = ref(db, "tarefas/" + user);
const newTaskRef = push(taskListRef);
// etc
const handleDelete = (key) => {
remove(taskListRef).then(() => {
const findTasks = tasks.filter((item) => item.key !== key);
setTasks(findTasks);
});
};
So, this remove(taskListRef) is my problem. I don't know how to call it properly regarding the reference to the data location.
I've tried: remove(taskListRef.child(user)), remove(taskListRef.child(key)) etc... and a bunch of other similar things. The error always: wrong reference.
Here is the repo. Please, help. Thank you all in advance.
P.S.: hopefully I won't have to ask a similar question regarding update().

undefined evaluating frames.endCoordinates.height

i had upgraded RN to 0.59.1 and updated native base to 2.13.5.
getting error
"undefined frames.endCoordinates.height"
when i try for textinput.
Native-Base Content is internally using
react-native-keyboard-aware-scroll-view
this is function from KeyboardAwareHOC of react-native-keyboard-aware-scroll-view
_updateKeyboardSpace = (frames: Object) => {
if (this.props.enableAutomaticScroll) {
let keyboardSpace: number =
frames.endCoordinates.height + this.props.extraScrollHeight
if (this.props.viewIsInsideTabBar) {
keyboardSpace -= _KAM_DEFAULT_TAB_BAR_HEIGHT
}
I can't grasp your intentions with your question. But what you want to do seems like this.
<KeyboardAwareScrollView
onKeyboardWillShow={(frames: Object) => {
console.log('Keyboard event', frames)
}}>
Is this right? You just saw the code in which the 'react-native-keyboard-aware-scroll-view' module was made.

Vue-Native checkbox change value

I want to be able to change the value of a checkbox by clicking on it. recentContacts are loading just fine, and specifying initial checked values in the computed function works well. The :on-press seems to change the value but does not reflect in the UI.
Please Help
Template
<nb-list>
<nb-list-item v-for="contact in recentContacts" v-bind:key="contact.uid">
<nb-checkbox :on-press="() => contact.checked =! contact.checked" :checked="contact.checked"></nb-checkbox>
<nb-text>{{contact.firstName}} {{contact.lastName}}</nb-text>
</nb-list-item>
</nb-list>
Code
export default {
computed: {
recentContacts() {
return store.state.admin.userData.recentContacts.map(rc => {
rc.checked = false;
return rc;
});
}
},
}
EDIT:
I am guessing because VUEX is imutable. I've got this to work by having recentContacts inside of the data attribute instead of computed just not how I want to do things.

jest snapshot testing: how to ignore part of the snapshot file in jest test results

Problem: ignore some part of the .snap file test results
the question here: there are some components in my test that have a random values and i don't really care about testing them. is there any way to ignore part of my X.snap file? so when i run tests in the future it won't give me test fail results.
Now you can also use property matcher for these cases.
By example to be able to use snapshot with these object :
const obj = {
id: dynamic(),
foo: 'bar',
other: 'value',
val: 1,
};
You can use :
expect(obj).toMatchSnapshot({
id: expect.any(String),
});
Jest will just check that id is a String and will process the other fields in the snapshot as usual.
Actually, you need to mock the moving parts.
As stated in jest docs:
Your tests should be deterministic. That is, running the same tests multiple times on a component that has not changed should produce the same results every time. You're responsible for making sure your generated snapshots do not include platform specific or other non-deterministic data.
If it's something related to time, you could use
Date.now = jest.fn(() => 1482363367071);
I know it's quite old question but I know one more solution. You can modify property you want to ignore, so it will be always constant instead of random / dynamic. This is best for cases when you are using third party code and thus may not be able to control the non deterministic property generation
Example:
import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Card from './Card';
import toJSON from 'enzyme-to-json';
Enzyme.configure({ adapter: new Adapter() });
describe('<Card />', () => {
it('renders <Card /> component', () => {
const card = shallow(
<Card
baseChance={1}
name={`test name`}
description={`long description`}
imageURL={'https://d2ph5fj80uercy.cloudfront.net/03/cat1425.jpg'}
id={0}
canBeIgnored={false}
isPassive={false}
/>
);
const snapshot = toJSON(card);
// for some reason snapshot.node.props.style.backgroundColor = "#cfc5f6"
// does not work, seems the prop is being set later
Object.defineProperty(snapshot.node.props.style, 'backgroundColor', { value: "#cfc5f6", writable: false });
// second expect statement is enaugh but this is the prop we care about:
expect(snapshot.node.props.style.backgroundColor).toBe("#cfc5f6");
expect(snapshot).toMatchSnapshot();
});
});
You can ignore some parts in the snapshot tests replacing the properties in the HTML. Using jest with testing-library, it would look something like this:
it('should match snapshot', async () => {
expect(removeUnstableHtmlProperties(await screen.findByTestId('main-container'))).toMatchSnapshot();
});
function removeUnstableHtmlProperties(htmlElement: HTMLElement) {
const domHTML = prettyDOM(htmlElement, Infinity);
if (!domHTML) return undefined;
return domHTML.replace(/id(.*)"(.*)"/g, '');
}
I used this to override moment's fromNow to make my snapshots deterministic:
import moment, {Moment} from "moment";
moment.fn.fromNow = jest.fn(function (this: Moment) {
const withoutSuffix = false;
return this.from(moment("2023-01-12T20:14:00"), withoutSuffix);
});