How can i make a button actvate my searchSpell function? - reactjs

i am finishing my first react project. But I cant make this button work. I keep giving me the same error below
error console message: Uncaught TypeError_axios_api_js__WEBPACK_IMPORTED_MODULE_1__.default.request is not a function
code:
function Header(){
const { searchSpell } = Hooker();
const [whatSpell, setWhatSpell] = useState()
function pesquisar () {
if(!whatSpell){
alert("escreva alguma coisa antes de pesquisar")
return
} else{
return searchSpell(whatSpell)
}
}
another code:
import { SpellContext } from "../provider.js"
function Hooker (){
const { spellState, searchSpell } = useContext(SpellContext)
return { spellState, searchSpell }
}
export default Hooker
and the function one:
function BaseInfo({ children }){
const [spellState, setSpellState] = useState({
name: undefined,
desc: undefined,
higher_level: undefined,
range: undefined,
components: undefined,
material: undefined,
ritual: false,
duration: undefined,
concentration: false,
casting_time: undefined,
level: 0,
});
const searchSpell = (spellName) => {
api.request(spellName).then(function(response) {
setSpellState(prevState => ({
...prevState,
name: response.data.name,
desc: response.data.desc,
higher_level: response.data.higher_level,
range: response.data.range,
components: response.data.components,
material: response.data.material,
ritual: response.data.ritual,
duration: response.data.duration,
concentration: response.data.concentration,
casting_time: response.data.duration,
level: response.data.duration,
})
)
})
console.log(spellState.duration)
}
const contextValue = {
spellState,
searchSpell: useCallback((spellName) => searchSpell(spellName), []),
}
return(
<SpellContext.Provider value={contextValue}>
{children}
</SpellContext.Provider>
)
}
export default BaseInfo

I don't think it's the button's fault. The error message indicates you're calling searchSpell, but there is something wrong with the way you're writing the API request.
If you're using axios as the error suggests. Check the axios documentation for proper installation, importing and usage.
Example usage for your use case:
import axios from "axios"
// ... ...
axios.request(spellName).then(function() {
// ... ...

Related

Testing custom hook React

I created a hook
export function useRedirectStartParams() {
const scenarios: IScenario[] = useSelector(scenariosSelector);
const block: IBlockItem = useSelector(selectedBlockSelector);
const [redirects, setRedirects] = useState<IDropdownEl[]>([]);
useEffect(() => {
const newRedirects =
block?.block_data?.redirects?.map((block: any) => {
const scenarioName = scenarios.find(
(scenario) => scenario.id === block.scenario_id
)?.name;
return {
name: scenarioName,
val: {
scenarioId: block.scenario_id,
blockId: block.id,
},
};
}) || [];
setRedirects(newRedirects);
}, [block, scenarios]);
return { redirects };
}
use it in my component
const { redirects } = useRedirectStartParams();
and then try to test it with jest like this
import { useRedirectStartParams } from "#hooks/useRedirectStartParams";
jest.mock("#hooks/useRedirectStartParams");
beforeEach(() => {
useRedirectStartParams.mockReturnValueOnce({
redirects: [{ name: "ad", val: "123" }],
});
})
but got error that redirects are undefined.
I also tried to mock hook this way
jest.mock("#hooks/useRedirectStartParams", () => jest.fn());
And it didn't help me
I expect that redirects won't be undefined. Not renderHook. i want to mock value of hook for component

How to get state variable names from names(string) value in React Native?

1. I set name in statesCorelatedFields and setStatesCorelatedFields inside below codes,
how can I get state and setState variables from there? (please see below example)
2. Does my below approach right?
3. Any suggestion will be highly appreciated.
I am using react native 0.68.5.
Previously, I used class component, now I am migrating to function component.
I have a reuseable file and App file like below:
reuseable.js
// import ...
export const handleFocus = (
state,
setState,
focusStyle,
// array of state variables of corelated fields
statesCorelatedFields,
// array of setState methods of corelated fields
setStatesCorelatedFields,
// blur style if no text value
blurNoTextStyle,
) => {
const stateData = { ...state };
stateData.styleName = { ...focusStyle };
// for corelated fields: empty value and set blurNoTextStyle
if (statesCorelatedFields.length) {
let stateCorelatedFieldData;
for (i = 0; i < statesCorelatedFields.length; i++) {
stateCorelatedFieldData = { ...statesCorelatedFields[i] };
stateCorelatedFieldData.value = '';
stateCorelatedFieldData.styleName = { ...blurNoTextStyle };
setStatesCorelatedFields[i](stateCorelatedFieldData);
}
}
setState(stateData);
};
// export const handleChangeText=(state, setState, text, ...)=>{...}
// export const handleBlur=(state, setState, ...)=>{...}
// ...
App.js
// import ...
// import all methods from reuseable.js
const App = () => {
const [email, setEmail] = useState({
name: 'email',
value: '',
styleName: { ...styles.blurNoTextStyle },
error: '',
statesCorelatedFields: [],
setStatesCorelatedFields: [],
});
const [countryCode, setCountryCode] = useState({
name: 'countryCode',
value: '',
styleName: { ...styles.blurNoTextStyle },
error: '',
// I set name here; how can I get state and setState variable from here
statesCorelatedFields: ['phoneNumber'],
setStatesCorelatedFields: ['setPhoneNumber'],
});
const [phoneNumber, setPhoneNumber] = useState({
name: 'phoneNumber',
value: '',
styleName: { ...styles.blurNoTextStyle },
error: '',
statesCorelatedFields: [],
setStatesCorelatedFields: [],
});
return (
<>
{/* components */}
<TextInput
value={countryCode.value}
onChangeText={(text) => handleChangeText(countryCode, setCountryCode, text)}
onFocus={() => handleFocus(countryCode, setCountryCode, styles.focusStyle, countryCode.statesCorelatedFields, countryCode.setStatesCorelatedFields)}
onBlur={() => handleBlur(countryCode, setCountryCode)}
/>
{/* other components */}
</>
);
}
const styles = StyleSheet.create({
// styles goes here
});
export default App;
Thanks in advance.
Moves this setStatesCorelatedFields out of the loop body you are updating the state on every iteration which doesn't need. It causes to slow down your component
you can do like this:
if (statesCorelatedFields.length) {
let stateCorelatedFieldData;
for (i = 0; i < statesCorelatedFields.length; i++) {
stateCorelatedFieldData = { ...statesCorelatedFields[i] };
stateCorelatedFieldData.value = "";
stateCorelatedFieldData.styleName = { ...blurNoTextStyle };
}
setStatesCorelatedFields[i](stateCorelatedFieldData);
}

the refresh the page i get TypeError: Cannot read property 'Location' of undefined

Hello I have an application in react and it is working perfectly. All routes, page loads. Everything perfect. However, when entering the FarmProperty page and trying to reload it (F5) the error TypeError: Cannot read property 'tenant_account' of undefined occurs.
FarmProperty.js
import { connect } from 'react-redux';
import * as actions from '../../store/actions/farmProperty';
class FarmProperty extends Component {
state = {
page: 0,
limit: 15,
msg: "",
erro: "",
success: "",
loading: false,
openModal: false,
id_delete: "",
tenant_account_id_delete: "",
apiData: false
}
componentDidMount() {
this.getFarmProperties();
}
componentDidUpdate(nextProps) {
if (!this.props.user && nextProps.user) this.getFarmProperties();
this.receiveApiData();
}
getFarmProperties() {
const { page, limit } = this.state;
const { farm_properties, user } = this.props;
//console.log(user);
this.props.getFarmProperties(user.tenant_account.id, page, limit);
if (this.props.location.state) {
this.setState({ msg: this.props.location.state.msg });
this.props.location.state.msg = "";
}
if (farm_properties === "undefined") return null;
}
receiveApiData() {
if (typeof this.props.farm_properties !== "undefined" && this.props.farm_properties !== null
&& !this.state.apiData && this.props.farm_properties.data.currentPageNumber === this.state.page) {
this.setState({ apiData: true });
}
}
render() {
return (
<>
</>
)
}
}
const mapStateToProps = state => ({
farm_properties: state.farmProperty.farm_properties,
user: state.auth.user
})
export default connect(mapStateToProps, actions)(FarmProperty);
I believe the problem lies in the function
this.props.getFarmProperties (user.tenant_account.id, page, limit);
when I'm passing the user.tenant_account.id parameter. This parameter is the user who is logged in to the application and I need to get this information, but if there is any other way to get this information, I would be grateful for the help.

How to add new key and vaule from object inside Array?

I am using ReactJSand Redux using the code below show how I am tring to add a new key:value in each object. Actually the error are:
Console log: Uncaught (in promise) TypeError: Cannot read property '0' of undefined
Web: TypeError: Cannot read property '0' of undefined
The data received from the API is:
The complete code is:
import React from "react";
import axios from "axios";
import TableData from "../TableData";
import CustomForm from "../FormCliente";
import Modal from "../Modal";
//Función que conecta un componente a Redux store.
import { connect } from "react-redux";
import { createBrowserHistory } from 'history';
class ClienteList extends React.Component {
state = {
DataFromApi: []
};
fetchArticles = () => {
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.headers = {
"Content-Type": "application/json",
Authorization: `Token ${this.props.token}`,
};
axios.get("http://192.168.196.49:8000/clientes/api/").then(res => {
this.setState({
DataFromApi: res.data
});
});
}
componentDidMount() {
this.fetchArticles();
}
componentWillReceiveProps(newProps) {
if (newProps.token) {
this.fetchArticles();
}
}
render() {
console.log("Token_desde_connect:", this.props.token);
const history = createBrowserHistory();
const location = history.location;
console.log("debug_1.1: ", location)
const dummy = event => {
console.log('mostrando dummy:', event.target.id);
}
const encabezado = [
{
label: 'Cliente',
field: 'nombre',
sort: 'asc',
width: 150
},
{
label: 'Fecha de alta',
field: 'fecha_alta',
sort: 'asc',
width: 270
},
{
label: 'Usuario ID',
field: 'usuario_id',
sort: 'asc',
width: 270
},
{
label: 'Herramientas',
field: '',
sort: 'asc',
width: 270
}
];
console.log("#-Before-#Data_from_API: ", this.state.DataFromApi);
    // Modificar el array con los datos obtenidos de la API.
    //for (let x in this.state.DataFromApi){
//console.log("#-valor_x:", x, "-#Data_from_API: ", this.state.DataFromApi[x]);
      //this.setState.DataFromApi[x] = Object.assign({ coco: x },this.stateDataFromApi[x] ) ;
      //console.log("#-Inside FOR -#New_Data_from_API: ", this.state.DataFromApi[x] );
//Otra forma de hacer:
//console.log("#-Before-#Data_from_API: ", this.state.DataFromApi);
// Modificar el array con los datos obtenidos de la API.
//let data=this.state.DataFromApi;
//data.forEach( (obj) => obj.city="Spain");
//this.setState({ DataFromApi:data})
    //};
//console.log("#Al finalizar el FOR_ fuera -#New_Data_from_API: ", this.state.DataFromApi );
//this.setState((prevState) => {
// DataFromApi: prevState.DataFromApi.map((obj) => ({
// ...obj,//<- This line will copy the entire object
// myKey: obj.myValue,//<- And this will add/override the property in this obj
// })
//);
this.setState((prevState) => ({
DataFromApi: prevState.DataFromApi.map((x) => ({
...x,//<- This line will copy the entire object
coco: x,//<- And this will add/override the property in this obj
}))
}));
console.log("#-After-#Data_from_API: ", this.state.DataFromApi);
return (
<div>
<Modal requestType="post" btnText="Guardar"/>
<TableData data={this.state.DataFromApi} Encabezado={encabezado}/> <br />
<h2> Create an article </h2>
<CustomForm requestType="post" itemID={null} btnText="Create" />
<button id="dummy" onClick={dummy}>Dummy button</button>
</div>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(ClienteList);
ERROR:
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
First of all, having your setState inside a loop is not a good idea, what you want to do in this case is pass a function to setState and that function will receive the "previous" (current) state.
this.setState((prevState) => ({
DataFromApi: prevState.DataFromApi.map((x) => ({
...x,//<- This line will copy the entire object
coco: x,//<- And this will add/override the property in this obj
}))
}));
It's also recommended to use this method (passing a function) when you're trying to update your state, based on the previous state, like this case, you're modifying your array, this is because this.setState is asynchronous and you can run into some problems if you don't use the function approach under this circumstances.
I hope this helps.
Update: Missing parenthesis, I used my editor this time so this works, I apologize about that.

How to properly manage the order data is received and DOM updated in React Hooks

I am using React Hooks and I want to use useMemo to trigger rerenders if and only if certain data changes.
i am also using apollo and I have a useQuery graphql query that I want to refresh under certain circumstances. The problem is, I'm getting some odd behaviour - sometimes the data just doesn't load. Also sometimes the context is not ready and no variables are passed to the useQuery.
My useMemo hook seems like it's repeating code, but getting rid of any of these if statements breaks the page.
Here is my functional component:
function Accounts(props) {
const userContext = useContext(UserContext)
const accountContext = useContext(AccountContext)
const parentAccountID = userContext.userState.accountId
const [parentAccountIDs, setParentAccountIDs] = useState(null)
const [vars, setVars] = useState({
parentIds: parentAccountIDs,
offset: accountContext.accountState.data.accountsOffset,
limit: accountContext.accountState.data.accountsLimit
});
const {
loading: loadingAccountUsers,
error: errorAccountUsers,
data: dataAccountUsers
} = useQuery(GET_ACCOUNT_USERS, {
variables: {
accountId: parentAccountID
}
})
const {
loading: loadingAccounts,
error: errorAccounts,
data: dataAccounts,
refetch: refetchAccounts
} = useQuery(GET_ACCOUNTS, {
variables: {vars}
})
const {
loading: loadingAccountsTotal,
error: errorAccountsTotal,
data: dataAccountsTotal,
refetch: refetchAccountsTotal
} = useQuery(TOTAL_ACCOUNTS, {
variables: {vars}
})
const setParentIDsHandler = (id) => {
setParentAccountIDs(String(id))
}
const setOffset = (offset, limit) => {
console.log("SET OFFSET", offset, limit)
accountContext.accountDispatch({
type: SET_ACCOUNTS_OFFSET,
payload: {
offset: offset,
limit: limit
}
})
setVars({
parentIds: parentAccountIDs,
offset: accountContext.accountState.data.accountsOffset,
limit: accountContext.accountState.data.accountsLimit
})
}
useMemo(() => {
if (dataAccountsTotal) {
accountContext.accountDispatch({type: SET_ACCOUNTS_TOTAL, payload: dataAccountsTotal})
console.log("TOTAL ACCOUNTS", accountContext.accountState.data.accountsTotal)
}
if (dataAccounts && dataAccountUsers && vars) {
refetchAccounts(vars)
accountContext.accountDispatch({type: GET_PARENT_ACCOUNT, payload: dataAccountUsers})
accountContext.accountDispatch({type: SET_ACCOUNTS, payload: dataAccounts})
setParentIDsHandler(dataAccountUsers.accountUsers[0].account.id)
}
}, [
dataAccounts,
dataAccountsTotal,
dataAccountUsers,
errorAccounts,
loadingAccounts,
parentAccountIDs,
vars
])
return (
<Fragment>
{
accountContext.accountState.data.accounts &&
!loadingAccountUsers &&
!errorAccountUsers &&
!loadingAccounts &&
!errorAccounts &&
parentAccountIDs &&
accountContext.accountState.data.accountUsers
? <AccountsGrid setOffset={setOffset}/> : <SpinnerLoader />}
</Fragment>
)
}
export default Accounts
When my handler function is called, sometimes the data being passed to the AccountsGrid component gets out of sync with the data from the server. How can I force React to wait for the data and only show it when it's available?

Resources