I've written a file which contains a Table that should display codes when there are pushed inside the array codes with prop name code (e.x. "848389494")
now every time the function addNewCode is called it should update the _codeData Object but it's not possible because its an outer scouped function. i cant move it inside ScannerResultTable because addNewCode should be able to be exported and used in another Component.
but i dont know how its not possible to useEffect and keep track on "codes" but it wont allow it because it's an outerscouped var.
thanks for your help-
const codes = []
export function addNewCode(value){
codes.push({ code: value });
}
export default function ScannerResultTable() {
const [_codeData, setCodeData] = useState([]);
useEffect(() => {
console.log("Hi im rendering");
setCodeData(codes);
}, []);
const [tableData, setTableData] = useState(_codeData);
Instead of using a globally defined variable codes, you can make use of React context and make the codes a state in some parent components and pass down the utility function to update the codes to the child components that are gonna update it.
More details on how to use react context can be found here
Related
I'm using the library React Datasheet Grid, the main component has a property called OnActiveCellChange, to which i'm passing my custom function:
const [selectedCell, setSelectedCell] = useState([])
...
function handleCellSelection({ cell }) {
if(cell) {
const {row, col} = cell;
const newData = data[row][col];
if(!newData.unpickable) {
console.log(selectedCell); // prints empty array
setSelectedCell(selectedCell => [...selectedCell, newData.value]);
}
}
}
...
<DataSheetGrid
className={'overwriteDisabledStyles'}
value={data}
onChange={setData}
columns={columns}
onActiveCellChange={handleCellSelection}
headerRowHeight={false}
gutterColumn={false}
lockRows
/>
The problem is that I wish to make some checks with the state variable "selectedCell", while I managed to update the state from with the functional form, I can't access the the state variable. I managed to use the variable using "useRef".
I want to know if I can tackle the problem in any other way.
EDIT:
Trying to clarify my question:
What I want is to, inside the handleCellSelection function, make some checks before inserting the newData using the setSelectedCell. Like searching the selectedCell array for existing values:
const valueAlreadyExists = selectedCell.some((existingCell) => {
return existingCell === newData.value
});
Yet, when the handleCellSelection function is called, the value of selectedCell is always an empty array. It should be the values that are being inserted in the array. I know there are values there because when I console.log outside the handleCellSelection they appear correctly.
So, I managed to access them inside the handleCellSelection using useRef() but what I am searching for is another option to solve this.
I use a react module that manages the use of spreadsheets:
react-spreadsheet https://github.com/iddan/react-spreadsheet/
In my project, I need several spreadsheets, and therefore several tables that the user can add, modify, delete on the fly
At the beginning, I wanted to use a big useState variable where the data arrays would be concentrated in the form : stateData = [ [...arrays], [...arrays...] ]
But the module, which uses an OnChange function taking as value the setData, seems to bug when my stateData variable contains different arrays.
<Spreadsheet key={index} className='table' columnLabels={stringLabelCol} rowLabels={stringLabelRow} data={stateData[index]} onChange={setData} />
As I can't manage everything in one UseState with this module,
is it possible to create a series of UseState inside a loop ?
It seems to me that it is a bad practice but I am really blocked
Thank you for reading my text... :/
Seeing your code and your comment, I'm assuming that:
You have one useState named data with ALL your data in it
You have multiple spreadsheets
For each spreadsheet, you want to pass the sheetData and the onChange that updates it
The issue in your code is that you're setting onChange={setData}, meaning any change will override the WHOLE data object, not just the targeted index.
What you want to do is have your onChange function be a function that updates only the right part of your state. So you'd do it like so:
const [data, setData] = useState([])
const updateSheetData = (index, sheetData) => {
// We clone the current state
const tempData = [...data]
// We update the right index
tempData[index] = sheetData
// This is now the new state
setData(tempData)
}
//...
// the onChange function for our component will use our custom function
<Spreadsheet
key={index}
className='table'
columnLabels={stringLabelCol}
rowLabels={stringLabelRow}
data={stateData[index]}
onChange={(newData) => updateSheetData(index, newData)}
/>
Then you'll also have to correctly update the data state whenever you add a new sheet or remove a sheet, to make sure the index are updated. But the idea is the same
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.
I have two different files currently (file1.jsx and file2.jsx both in the same directory). file2.jsx depends on the list of file1.jsx, so I want to be able to call the list somehow. This is my current implementation.
file1.jsx:
function file1 {
// this is the list I want to call in file2.jsx
const [currentSelection, setCurrentSelection] = uuseState([]);
// also tried export const [currentSelection, setCurrentSelection] = uuseState([]);
...
}
file2.jsx:
//gave me errors
import { currentSelection } from "file1";
function file2 {
...
}
If I can get some help, I would much appreciate it!
State in react-native is internal data-set which affects the rendering of components .It is private and fully controlled by the component .
However if you want to use value of currentSelection in file2 , you can store the value of currentSelection in some central store like redux and then fetch it in file2.
Firstly, you wrote uuseState which should be useState, second for you solution. There are many ways to store an array (assuming that you what to pass to second screen by initial value of your use state is empty array)
You can pass it by react Navigation's params if you are using it,
You can store it using async storage and call that storage on second screen.
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)