Accessing Redux selector value in a custom hook - javascript

I'm writing my first hook and I also use redux.
I'm listening to orientation sensor data from the mobile device in React native and when it updates I filter it to see if the new value is different than the old value before I send it over to redux state to be stored.
I'm noticing in the filterData method the data is always null. But if I console log the storedVal in the render I see it's always being updated and it's updated in the Redux store as well.
But for some reason filterData only has access to the initial value and doesn't get the updated values. Any idea how to fix this?
const storedVal = useSelector(selectors.selectStoredVal);
const filterData = useCallback(
() => {
console.log(storedVal);
},
[storedVal]
);
useEffect(
() => {
orientation.pipe(filter(filterData)).subscribe((data) => {
console.log('Data filtered correctly, new data received here');
}
}
),
[];
}

An empty dependency array for useEffect means that the callback function within it will only run once (on component mount).
useCallback is creating a function that is being passed into the filter function. Because storedVal is a dependency for filteredData, went storedVal changes and filteredData is updated to a new function, your useEffect still has a reference to it's old value.
Try adding [filteredData] to your dependency array for the useEffect.

Related

I get error while trying to read text from file in reactjs/tauri

im building crypto wallet in reactjs and then i will make it in tauri but what im tryng to do now is to read mnemonic from text file but i get this error img
the code is this:
fetch(raw)
.then(r => r.text())
.then(text => {
console.log(text); // console logs output
});
const [computer] = useState(
new Computer({
mnemonic: (text), // i want here to be output but i get that error
There are a couple problems here. The initial problem, and the reason the error occurred, is because the text variable is out of scope when you are calling it inside the useState hook. You will need to set the state value when you have reference to the text variable.
The second problem is that you are wanting to set the initial value of the a state in a react component based off an asynchronous query. Since an asynchronous value cannot be available at the initial render, you need to combine the useState hook and the useEffect hook to set the value after the initial load.
With such limited code shown, i will try to fill in the gaps and make an example of what i think you are looking for:
function Component() {
const [computer, setComputer] = useState("");
useEffect(() => {
fetch(raw).then(r => r.text()).then(text => {
setComputer(new Computer({ mnemonic: text }))
})
}, [])
return (
// whatever you render
)
}
This way, at render your component will have a default value of "" and then when the async fetch call has finished it will update the value. If you pass an empty array as the second parameter to the useEffect hook, it will only be called on the initial render.

Can't find the way to useSelector from redux-toolkit within event handler and pass params to it

There is an event handler for click and when it triggered i want to pull specific data from redux using selector where all logic many-to-many is implemented. I need to pass id to it in order to receive its individual data. Based on rules of the react the hooks can be called in function that is neither a React function component nor a custom React Hook function.
So what is the way to solve my problem ?
const handleMediaItemClick = (media: any): void => {
// For example i check media type and use this selector to pull redux data by id
const data = useSelector(playlistWithMediaSelector(imedia.id));
};
As stated in the error message, you cannot call hooks inside functions. You call a hook inside a functional component and use that value inside the function. The useSelector hook updates the variable each time the state changes and renders that component.
Also, when you get data with useSelector, you should write the reducer name you need from the redux state.
const CustomComponent = () => {
// The data will be updated on each state change and the component will be rendered
const data = useSelector((state) => state.REDUCER_NAME);
const handleMediaItemClick = () => {
console.log(data);
};
}
You can check this page for more information.https://react-redux.js.org/api/hooks#useselector
You should probably use local state value to track that.
const Component = () => {
const [imediaId, setImediaId] = useState(null);
const data = useSelector(playlistWithMediaSelector(imediaId));
function handleMediaClick(id) {
setImediaId(id)
}
useEffect(() => {
// do something on data
}, [imediaId, data])
return <div>...</div>
}
Does that help?
EDIT: I gather that what you want to do is to be able to call the selector where you need. Something like (considering the code above) data(id) in handleMediaClick. I'd bet you gotta return a curried function from useSelector, rather than value. Then you would call it. Alas, I haven't figured out how to that, if it's at all possible and whether it's an acceptable pattern or not.

Why is my state not updating with fetched data in time for the useEffect to update my DOM with the new state?

I am new to using hooks in React. I am trying to fetch data when the component first mounts by utilizing useEffect() with a second parameter of an empty array. I am then trying to set my state with the new data. This seems like a very straightforward use case, but I must be doing something wrong because the DOM is not updating with the new state.
const [tableData, setTableData] = useState([]);
useEffect(() => {
const setTableDataToState = () => {
fetchTableData()
.then(collection => {
console.log('collection', collection) //this logs the data correctly
setTableData(collection);
})
.catch(err => console.error(err));
};
setTableDataToState();
}, []);
When I put a long enough timeout around the setTableData() call (5ms didn't work, 5s did), the accurate tableData will display as expected, which made me think it may be an issue with my fetch function returning before the collection is actually ready. But the console.log() before setTableData() is outputting the correct information-- and I'm not sure how it could do this if the data wasn't available by that point in the code.
I'm hoping this is something very simple I'm missing. Any ideas?
The second argument passed to useEffect can be used to skip an effect.
Documentation: https://reactjs.org/docs/hooks-effect.html
They go on to explain in their example that they are using count as the second argument:
"If the count is 5, and then our component re-renders with count still
equal to 5, React will compare [5] from the previous render and [5]
from the next render. Because all items in the array are the same (5
=== 5), React would skip the effect. That’s our optimization."
So you would like it to re-render but only to the point that the data changes and then skip the re-render.

Unable to set state hook using useDispatch hook in React

I am using useEffect hook to dispatch action to my redux store on component load. Here is code:
const dispatch = useDispatch()
const hotelList = useSelector(state => state.hotels)
const [updatedList, setUpdatedList] = useState([...hotelList])
useEffect(() => {
dispatch(fetchHotels())
// setUpdatedList(hotelList) -- I've tried using this line here but still gets empty array
}, [])
It works fine because when I try to do {console.log(hotelList} I get array of objects from the redux store.
However, when I try to do setUpdatedList(hotelList) or even set initial state it does not work and I get empty array. How can I fix it?
P.S just to clarify I am 100% sure that action was correctly dispatched to the store as I can see the results in console.log as well as in redux dev tools.

React hooks: Not getting the state update when using useEffect

I'm having an issue when mixing useState and the useEffect hook. I can't seem to reference the new query state in onReady().
function Foo() {
const [ query, setQuery ] = React.useState('initial query');
React.useEffect(() => {
myLibClient.onReady(onReady)
}, []);
function onReady() {
const newQuery = myLibClient.createQuery({ options });
setQuery(newQuery);
console.log(query); // initial query :(
}
return null;
}
Can anyone see what I'm doing wrong or explain why this doesn't work?
The issue here is that like this.setState in the class-based react components, the setQuery function also sets the state asynchronously.
See Reference react docs and RFC: Why it is asynchronous?
So if you try to access the value just after setting the state, you'll get the older value.
You can verify this behavior here. https://codesandbox.io/s/2w4mp4x3ry. (See the file named Counter.js)
You'll see that before and after values for counter are same.
If you want to access the updated value, you can access it in the next render cycle. I have created another example where you can see that new query value is being rendered.
https://codesandbox.io/s/8l7mqkx8wl (See the file named Counter.js)

Categories