映射数组在将本地存储放入 React Hooks useState 时出现错误渲染(一切看起来都颠倒了)* 第一次代码看起来很乱
Mapping array get error rendering when doing localstorage into React Hooks useState (everything looks upside down) * first time code looks messy
import React, { useState, useEffect } from 'react';
import {
FormControl,
Form,
Button,
Container,
Card,
Row,
Col,
} from 'react-bootstrap';
import { nanoid } from 'nanoid';
import axios from 'axios';
import * as usertz from 'user-timezone';
import './card.css';
import slp from '../assets/SLP.png';
import ronin from '../assets/ronin.png';
const AxieAPI = () => {
const [toggle, setToggle] = useState(false);
const [price, setPrice] = useState([{ current_price: '' }]);
const [addFormData, setAddFormData] = useState({
myName: '',
roninAddress: '',
manager: '',
scholar: '',
});
const [dataAll, setDataAll] = useState([
{
id: '',
myName: '',
roninAddress: '',
manager: '',
scholar: '',
data: {
slp: {
total: '',
claimableTotal: '',
lastClaimedItemA: '',
todaySoFar: '',
yesterdaySLP: '',
},
leaderboard: {
winRate: '',
winTotal: '',
drawTotal: '',
loseTotal: '',
elo: '',
rank: '',
name: '',
},
},
},
]);
const baseURL =
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=smooth-love-potion&order=market_cap_desc&per_page=100&page=1&sparkline=false';
// const {
// myName,
// roninAddress,
// manager,
// scholar,
// data: {
// slp: {
// total,
// claimableTotal,
// lastClaimedItemA,
// todaySoFar,
// yesterdaySLP,
// },
// leaderboard: { winRate, winTotal, drawTotal, loseTotal, elo, rank, name },
// },
// } = dataAll;
useEffect(() => {
async function fetchData() {
await axios.get(baseURL).then((response) => {
// eslint-disable-next-line
response.data.map((pri) => {
const answer = pri.current_price;
setPrice(answer);
});
});
// await localStorage.setItem('localData', JSON.stringify(dataAll));
const newData = JSON.parse(localStorage.getItem('localData'));
setDataAll(newData);
}
fetchData();
// eslint-disable-next-line
}, [dataAll]);
const userAddress = addFormData.roninAddress.slice(6);
var options = {
method: 'GET',
url: `https://axie-infinity.p.rapidapi.com/get-update/0x${userAddress}`,
params: { id: `0x${userAddress}` },
headers: {
'x-rapidapi-host': process.env.REACT_APP_HOST,
'x-rapidapi-key': process.env.REACT_APP_KEY,
},
};
const onChangeHandler = async (e) => {
// setRoninAddress(e.target.value);
await e.preventDefault();
try {
const fieldName = e.target.getAttribute('name');
const fieldValue = e.target.value;
const newFormData = { ...addFormData };
newFormData[fieldName] = fieldValue;
setAddFormData(newFormData);
} catch (error) {
console.log(error);
}
};
const onSubmitHandler = async (e) => {
await e.preventDefault();
await axios
.request(options)
.then(function (response) {
const newUser = {
id: nanoid(),
myName: addFormData.myName,
roninAddress: addFormData.roninAddress,
manager: addFormData.manager,
scholar: addFormData.scholar,
data: response.data,
};
const newUsers = [...dataAll, newUser];
setDataAll(newUsers);
// console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
localStorage.setItem('localData', JSON.stringify(dataAll));
// localStorage.setItem('localData', JSON.stringify(dataAll));
e.target.reset();
};
return (
<div>
<Container className="p-4">
<Button onClick={() => setToggle(!toggle)} className="mb-5">
Add Scholar
</Button>
{toggle && (
<Form onSubmit={onSubmitHandler}>
<Row className="mb-3">
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar Name</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="myName"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Ronin Address</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
// value={roninAddress}
placeholder="ronin:12345-54321"
name="roninAddress"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<Row>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Manager %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="manager"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="scholar"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<div className="d-grid gap-2 pt-3">
<Button type="submit" size="lg">
Add User
</Button>
</div>
</Form>
)}
<Container>
<Row>
{dataAll.slice(2).map((singleData) => {
const myName = singleData.myName;
const manager = singleData.manager;
const scholar = singleData.scholar;
const roninAddress = singleData.roninAddress;
const totalSlp = singleData.data.slp.total;
const claimableTotal = singleData.data.slp.claimableTotal;
const lastClaimedItemAt = singleData.data.slp.lastClaimedItemAt;
const todaySoFar = singleData.data.slp.todaySoFar;
const yesterdaySLP = singleData.data.slp.yesterdaySLP;
// const winRate = singleData.data.leaderboard.winRate;
// const winTotal = singleData.data.leaderboard.winTotal;
// const drawTotal = singleData.data.leaderboard.drawTotal;
// const loseTotal = singleData.data.leaderboard.lostTotal;
const elo = singleData.data.leaderboard.elo;
const rank = singleData.data.leaderboard.rank;
const name = singleData.data.leaderboard.name;
const unixTimeStamp = lastClaimedItemAt;
const dateTimeFormat = 'MMMM Do, YYYY h:mm ss A';
const datetime = usertz.datetime(unixTimeStamp, dateTimeFormat);
const newUnixTimeStamp = lastClaimedItemAt + 1209600;
const newdatetime = usertz.datetime(
newUnixTimeStamp,
dateTimeFormat
);
const totalSlpPrice = price * totalSlp;
const finaltotalSlpPrice = totalSlpPrice.toFixed(2);
return (
<Card
style={{
width: '22rem',
backgroundColor: '#4f4f4f',
padding: '20px',
marginTop: '30px',
marginRight: '10px',
}}
key={singleData.id}
>
<Card.Body>
<Card.Title className="text-center">{name}</Card.Title>
Scholar: <span className="font-weight-bold">{myName}</span>
<p className="address">
{' '}
<img src={ronin} alt="ronin" height="20px"></img>{' '}
{roninAddress}
</p>
<Card.Subtitle className="mb-2 text-muted"></Card.Subtitle>
<Row>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
In-Game SLP
<h2>
<span style={{ color: '#3cf0cb' }}>{totalSlp}</span>
<img height="35px" src={slp} alt={slp}></img>
</h2>
<p>USD {finaltotalSlpPrice}</p>
</div>
</Card.Text>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
Claimable SLP
<h2>
<span style={{ color: '#3cf0cb' }}>
{claimableTotal}
<img height="35px" src={slp} alt={slp}></img>
</span>
</h2>
</div>
</Card.Text>
</Row>
Previos Claim: {datetime}
<br />
Next Claim: {newdatetime}
<Card.Text className="bg-dark p-1">
MMR ⚔️ : {elo}
<br />
Rank : {rank}
<br />
SLP Today: {todaySoFar}
<br />
SLP Yesterday: {yesterdaySLP}
<br />
</Card.Text>
<Card.Text className="p-2 bg-dark">
Manager: {manager} % <br />
Scholar: {scholar} %
</Card.Text>
</Card.Body>
{/* <Button onRemove={onRemove}></Button> */}
</Card>
);
})}
</Row>
</Container>
</Container>
</div>
);
};
export default AxieAPI;
第一次挑战自己编写 localstorage 代码时,我编写的代码看起来颠倒了。谁能帮我纠正这个问题?数组映射似乎关闭,因为它出错了“无法读取 null 的属性”
i 反击另一个问题,即一旦 i 运行 npm start 。它没有记录第一个数据全部进入状态意味着它没有记录一个数据 return null ==> 导致映射数组错误就像一个链。
我一直在尝试调整 localstorage 保存数据并获取数据,似乎每次刷新时数据都会被擦除。我认为数据存储的 useEffect 和 Submit 存在一些代码错误 + 每次都必须 运行 将空数据保存到本地存储中以防止数组映射错误。
import React, { useState, useEffect } from 'react';
import {
FormControl,
Form,
Button,
Container,
Card,
Row,
Col,
} from 'react-bootstrap';
import { nanoid } from 'nanoid';
import axios from 'axios';
import * as usertz from 'user-timezone';
import './card.css';
import slp from '../assets/SLP.png';
import ronin from '../assets/ronin.png';
import useLocalStorage from './hooks/useLocalStorage';
const AxieAPI = () => {
const [toggle, setToggle] = useState(false);
const [price, setPrice] = useState([{ current_price: '' }]);
const [addFormData, setAddFormData] = useState({
myName: '',
roninAddress: '',
manager: '',
scholar: '',
});
const [dataAll, setDataAll] = useLocalStorage('localData', [
{
id: '',
myName: '',
roninAddress: '',
manager: '',
scholar: '',
data: {
slp: {
total: '',
claimableTotal: '',
lastClaimedItemA: '',
todaySoFar: '',
yesterdaySLP: '',
},
leaderboard: {
winRate: '',
winTotal: '',
drawTotal: '',
loseTotal: '',
elo: '',
rank: '',
name: '',
},
},
},
]);
const baseURL =
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=smooth-love-potion&order=market_cap_desc&per_page=100&page=1&sparkline=false';
useEffect(() => {
async function fetchData() {
await axios.get(baseURL).then((response) => {
// eslint-disable-next-line
response.data.map((pri) => {
const answer = pri.current_price;
setPrice(answer);
});
});
localStorage.setItem('localData', JSON.stringify(dataAll));
}
fetchData();
// eslint-disable-next-line
}, [dataAll]);
const userAddress = addFormData.roninAddress.slice(6);
var options = {
method: 'GET',
url: `https://axie-infinity.p.rapidapi.com/get-update/0x${userAddress}`,
params: { id: `0x${userAddress}` },
headers: {
'x-rapidapi-host': process.env.REACT_APP_HOST,
'x-rapidapi-key': process.env.REACT_APP_KEY,
},
};
const onChangeHandler = async (e) => {
// setRoninAddress(e.target.value);
await e.preventDefault();
try {
const fieldName = e.target.getAttribute('name');
const fieldValue = e.target.value;
const newFormData = { ...addFormData };
newFormData[fieldName] = fieldValue;
setAddFormData(newFormData);
} catch (error) {
console.log(error);
}
};
const onSubmitHandler = async (e) => {
await e.preventDefault();
await axios
.request(options)
.then(function (response) {
const newUser = {
id: nanoid(),
myName: addFormData.myName,
roninAddress: addFormData.roninAddress,
manager: addFormData.manager,
scholar: addFormData.scholar,
data: response.data,
};
const newUsers = [...dataAll, newUser];
setDataAll(newUsers);
// console.log(response.data);
localStorage.setItem('localData', JSON.stringify(dataAll));
})
.catch(function (error) {
console.error(error);
});
// localStorage.setItem('localData', JSON.stringify(dataAll));
e.target.reset();
};
return (
<div>
<Container className="p-4">
<Button onClick={() => setToggle(!toggle)} className="mb-5">
Add Scholar
</Button>
{toggle && (
<Form onSubmit={onSubmitHandler}>
<Row className="mb-3">
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar Name</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="myName"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Ronin Address</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
// value={roninAddress}
placeholder="ronin:12345-54321"
name="roninAddress"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<Row>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Manager %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="manager"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="scholar"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<div className="d-grid gap-2 pt-3">
<Button type="submit" size="lg">
Add User
</Button>
</div>
</Form>
)}
<Container>
<Row>
{dataAll.slice(1).map((singleData) => {
const myName = singleData.myName;
const manager = singleData.manager;
const scholar = singleData.scholar;
const roninAddress = singleData.roninAddress;
const totalSlp = singleData.data.slp.total;
const claimableTotal = singleData.data.slp.claimableTotal;
const lastClaimedItemAt = singleData.data.slp.lastClaimedItemAt;
const todaySoFar = singleData.data.slp.todaySoFar;
const yesterdaySLP = singleData.data.slp.yesterdaySLP;
// const winRate = singleData.data.leaderboard.winRate;
// const winTotal = singleData.data.leaderboard.winTotal;
// const drawTotal = singleData.data.leaderboard.drawTotal;
// const loseTotal = singleData.data.leaderboard.lostTotal;
const elo = singleData.data.leaderboard.elo;
const rank = singleData.data.leaderboard.rank;
const name = singleData.data.leaderboard.name;
const unixTimeStamp = lastClaimedItemAt;
const dateTimeFormat = 'MMMM Do, YYYY h:mm ss A';
const datetime = usertz.datetime(unixTimeStamp, dateTimeFormat);
const newUnixTimeStamp = lastClaimedItemAt + 1209600;
const newdatetime = usertz.datetime(
newUnixTimeStamp,
dateTimeFormat
);
const totalSlpPrice = price * totalSlp;
const finaltotalSlpPrice = totalSlpPrice.toFixed(2);
return (
<Card
style={{
width: '22rem',
backgroundColor: '#4f4f4f',
padding: '20px',
marginTop: '30px',
marginRight: '10px',
}}
key={singleData.id}
>
<Card.Body>
<Card.Title className="text-center">{name}</Card.Title>
Scholar: <span className="font-weight-bold">{myName}</span>
<p className="address">
{' '}
<img src={ronin} alt="ronin" height="20px"></img>{' '}
{roninAddress}
</p>
<Card.Subtitle className="mb-2 text-muted"></Card.Subtitle>
<Row>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
In-Game SLP
<h2>
<span style={{ color: '#3cf0cb' }}>{totalSlp}</span>
<img height="35px" src={slp} alt={slp}></img>
</h2>
<p>USD {finaltotalSlpPrice}</p>
</div>
</Card.Text>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
Claimable SLP
<h2>
<span style={{ color: '#3cf0cb' }}>
{claimableTotal}
<img height="35px" src={slp} alt={slp}></img>
</span>
</h2>
</div>
</Card.Text>
</Row>
Previos Claim: {datetime}
<br />
Next Claim: {newdatetime}
<Card.Text className="bg-dark p-1">
MMR ⚔️ : {elo}
<br />
Rank : {rank}
<br />
SLP Today: {todaySoFar}
<br />
SLP Yesterday: {yesterdaySLP}
<br />
</Card.Text>
<Card.Text className="p-2 bg-dark">
Manager: {manager} % <br />
Scholar: {scholar} %
</Card.Text>
</Card.Body>
</Card>
);
})}
</Row>
</Container>
</Container>
</div>
);
};
export default AxieAPI;
我似乎设法用 localStorage 修复了它。
如果你也遇到这样的可以看看
import React, { useState, useEffect } from 'react';
import {
FormControl,
Form,
Button,
Container,
Card,
Row,
Col,
} from 'react-bootstrap';
import { nanoid } from 'nanoid';
import axios from 'axios';
import * as usertz from 'user-timezone';
import './card.css';
import slp from '../assets/SLP.png';
import ronin from '../assets/ronin.png';
const AxieAPI = () => {
const [toggle, setToggle] = useState(false);
const [price, setPrice] = useState([{ current_price: '' }]);
const [addFormData, setAddFormData] = useState({
myName: '',
roninAddress: '',
manager: '',
scholar: '',
});
const [dataAll, setDataAll] = useState([
{
id: '',
myName: '',
roninAddress: '',
manager: '',
scholar: '',
data: {
slp: {
total: '',
claimableTotal: '',
lastClaimedItemA: '',
todaySoFar: '',
yesterdaySLP: '',
},
leaderboard: {
winRate: '',
winTotal: '',
drawTotal: '',
loseTotal: '',
elo: '',
rank: '',
name: '',
},
},
},
]);
const baseURL =
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=smooth-love-potion&order=market_cap_desc&per_page=100&page=1&sparkline=false';
// const {
// myName,
// roninAddress,
// manager,
// scholar,
// data: {
// slp: {
// total,
// claimableTotal,
// lastClaimedItemA,
// todaySoFar,
// yesterdaySLP,
// },
// leaderboard: { winRate, winTotal, drawTotal, loseTotal, elo, rank, name },
// },
// } = dataAll;
useEffect(() => {
async function fetchData() {
await axios.get(baseURL).then((response) => {
// eslint-disable-next-line
response.data.map((pri) => {
const answer = pri.current_price;
setPrice(answer);
});
});
// await localStorage.setItem('localData', JSON.stringify(dataAll));
const newData = JSON.parse(localStorage.getItem('localData'));
setDataAll(newData);
}
fetchData();
// eslint-disable-next-line
}, [dataAll]);
const userAddress = addFormData.roninAddress.slice(6);
var options = {
method: 'GET',
url: `https://axie-infinity.p.rapidapi.com/get-update/0x${userAddress}`,
params: { id: `0x${userAddress}` },
headers: {
'x-rapidapi-host': process.env.REACT_APP_HOST,
'x-rapidapi-key': process.env.REACT_APP_KEY,
},
};
const onChangeHandler = async (e) => {
// setRoninAddress(e.target.value);
await e.preventDefault();
try {
const fieldName = e.target.getAttribute('name');
const fieldValue = e.target.value;
const newFormData = { ...addFormData };
newFormData[fieldName] = fieldValue;
setAddFormData(newFormData);
} catch (error) {
console.log(error);
}
};
const onSubmitHandler = async (e) => {
await e.preventDefault();
await axios
.request(options)
.then(function (response) {
const newUser = {
id: nanoid(),
myName: addFormData.myName,
roninAddress: addFormData.roninAddress,
manager: addFormData.manager,
scholar: addFormData.scholar,
data: response.data,
};
const newUsers = [...dataAll, newUser];
setDataAll(newUsers);
// console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
localStorage.setItem('localData', JSON.stringify(dataAll));
// localStorage.setItem('localData', JSON.stringify(dataAll));
e.target.reset();
};
return (
<div>
<Container className="p-4">
<Button onClick={() => setToggle(!toggle)} className="mb-5">
Add Scholar
</Button>
{toggle && (
<Form onSubmit={onSubmitHandler}>
<Row className="mb-3">
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar Name</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="myName"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Ronin Address</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
// value={roninAddress}
placeholder="ronin:12345-54321"
name="roninAddress"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<Row>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Manager %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="manager"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="scholar"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<div className="d-grid gap-2 pt-3">
<Button type="submit" size="lg">
Add User
</Button>
</div>
</Form>
)}
<Container>
<Row>
{dataAll.slice(2).map((singleData) => {
const myName = singleData.myName;
const manager = singleData.manager;
const scholar = singleData.scholar;
const roninAddress = singleData.roninAddress;
const totalSlp = singleData.data.slp.total;
const claimableTotal = singleData.data.slp.claimableTotal;
const lastClaimedItemAt = singleData.data.slp.lastClaimedItemAt;
const todaySoFar = singleData.data.slp.todaySoFar;
const yesterdaySLP = singleData.data.slp.yesterdaySLP;
// const winRate = singleData.data.leaderboard.winRate;
// const winTotal = singleData.data.leaderboard.winTotal;
// const drawTotal = singleData.data.leaderboard.drawTotal;
// const loseTotal = singleData.data.leaderboard.lostTotal;
const elo = singleData.data.leaderboard.elo;
const rank = singleData.data.leaderboard.rank;
const name = singleData.data.leaderboard.name;
const unixTimeStamp = lastClaimedItemAt;
const dateTimeFormat = 'MMMM Do, YYYY h:mm ss A';
const datetime = usertz.datetime(unixTimeStamp, dateTimeFormat);
const newUnixTimeStamp = lastClaimedItemAt + 1209600;
const newdatetime = usertz.datetime(
newUnixTimeStamp,
dateTimeFormat
);
const totalSlpPrice = price * totalSlp;
const finaltotalSlpPrice = totalSlpPrice.toFixed(2);
return (
<Card
style={{
width: '22rem',
backgroundColor: '#4f4f4f',
padding: '20px',
marginTop: '30px',
marginRight: '10px',
}}
key={singleData.id}
>
<Card.Body>
<Card.Title className="text-center">{name}</Card.Title>
Scholar: <span className="font-weight-bold">{myName}</span>
<p className="address">
{' '}
<img src={ronin} alt="ronin" height="20px"></img>{' '}
{roninAddress}
</p>
<Card.Subtitle className="mb-2 text-muted"></Card.Subtitle>
<Row>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
In-Game SLP
<h2>
<span style={{ color: '#3cf0cb' }}>{totalSlp}</span>
<img height="35px" src={slp} alt={slp}></img>
</h2>
<p>USD {finaltotalSlpPrice}</p>
</div>
</Card.Text>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
Claimable SLP
<h2>
<span style={{ color: '#3cf0cb' }}>
{claimableTotal}
<img height="35px" src={slp} alt={slp}></img>
</span>
</h2>
</div>
</Card.Text>
</Row>
Previos Claim: {datetime}
<br />
Next Claim: {newdatetime}
<Card.Text className="bg-dark p-1">
MMR ⚔️ : {elo}
<br />
Rank : {rank}
<br />
SLP Today: {todaySoFar}
<br />
SLP Yesterday: {yesterdaySLP}
<br />
</Card.Text>
<Card.Text className="p-2 bg-dark">
Manager: {manager} % <br />
Scholar: {scholar} %
</Card.Text>
</Card.Body>
{/* <Button onRemove={onRemove}></Button> */}
</Card>
);
})}
</Row>
</Container>
</Container>
</div>
);
};
export default AxieAPI;
第一次挑战自己编写 localstorage 代码时,我编写的代码看起来颠倒了。谁能帮我纠正这个问题?数组映射似乎关闭,因为它出错了“无法读取 null 的属性”
i 反击另一个问题,即一旦 i 运行 npm start 。它没有记录第一个数据全部进入状态意味着它没有记录一个数据 return null ==> 导致映射数组错误就像一个链。
我一直在尝试调整 localstorage 保存数据并获取数据,似乎每次刷新时数据都会被擦除。我认为数据存储的 useEffect 和 Submit 存在一些代码错误 + 每次都必须 运行 将空数据保存到本地存储中以防止数组映射错误。
import React, { useState, useEffect } from 'react';
import {
FormControl,
Form,
Button,
Container,
Card,
Row,
Col,
} from 'react-bootstrap';
import { nanoid } from 'nanoid';
import axios from 'axios';
import * as usertz from 'user-timezone';
import './card.css';
import slp from '../assets/SLP.png';
import ronin from '../assets/ronin.png';
import useLocalStorage from './hooks/useLocalStorage';
const AxieAPI = () => {
const [toggle, setToggle] = useState(false);
const [price, setPrice] = useState([{ current_price: '' }]);
const [addFormData, setAddFormData] = useState({
myName: '',
roninAddress: '',
manager: '',
scholar: '',
});
const [dataAll, setDataAll] = useLocalStorage('localData', [
{
id: '',
myName: '',
roninAddress: '',
manager: '',
scholar: '',
data: {
slp: {
total: '',
claimableTotal: '',
lastClaimedItemA: '',
todaySoFar: '',
yesterdaySLP: '',
},
leaderboard: {
winRate: '',
winTotal: '',
drawTotal: '',
loseTotal: '',
elo: '',
rank: '',
name: '',
},
},
},
]);
const baseURL =
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=smooth-love-potion&order=market_cap_desc&per_page=100&page=1&sparkline=false';
useEffect(() => {
async function fetchData() {
await axios.get(baseURL).then((response) => {
// eslint-disable-next-line
response.data.map((pri) => {
const answer = pri.current_price;
setPrice(answer);
});
});
localStorage.setItem('localData', JSON.stringify(dataAll));
}
fetchData();
// eslint-disable-next-line
}, [dataAll]);
const userAddress = addFormData.roninAddress.slice(6);
var options = {
method: 'GET',
url: `https://axie-infinity.p.rapidapi.com/get-update/0x${userAddress}`,
params: { id: `0x${userAddress}` },
headers: {
'x-rapidapi-host': process.env.REACT_APP_HOST,
'x-rapidapi-key': process.env.REACT_APP_KEY,
},
};
const onChangeHandler = async (e) => {
// setRoninAddress(e.target.value);
await e.preventDefault();
try {
const fieldName = e.target.getAttribute('name');
const fieldValue = e.target.value;
const newFormData = { ...addFormData };
newFormData[fieldName] = fieldValue;
setAddFormData(newFormData);
} catch (error) {
console.log(error);
}
};
const onSubmitHandler = async (e) => {
await e.preventDefault();
await axios
.request(options)
.then(function (response) {
const newUser = {
id: nanoid(),
myName: addFormData.myName,
roninAddress: addFormData.roninAddress,
manager: addFormData.manager,
scholar: addFormData.scholar,
data: response.data,
};
const newUsers = [...dataAll, newUser];
setDataAll(newUsers);
// console.log(response.data);
localStorage.setItem('localData', JSON.stringify(dataAll));
})
.catch(function (error) {
console.error(error);
});
// localStorage.setItem('localData', JSON.stringify(dataAll));
e.target.reset();
};
return (
<div>
<Container className="p-4">
<Button onClick={() => setToggle(!toggle)} className="mb-5">
Add Scholar
</Button>
{toggle && (
<Form onSubmit={onSubmitHandler}>
<Row className="mb-3">
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar Name</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="myName"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Ronin Address</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
// value={roninAddress}
placeholder="ronin:12345-54321"
name="roninAddress"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<Row>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Manager %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="manager"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
<Form.Group as={Col} sm={12} lg={6}>
<Form.Label>Scholar %</Form.Label>
<FormControl
aria-label="Small"
aria-describedby="inputGroup-sizing-sm"
name="scholar"
type="number"
onChange={onChangeHandler}
/>
</Form.Group>
</Row>
<div className="d-grid gap-2 pt-3">
<Button type="submit" size="lg">
Add User
</Button>
</div>
</Form>
)}
<Container>
<Row>
{dataAll.slice(1).map((singleData) => {
const myName = singleData.myName;
const manager = singleData.manager;
const scholar = singleData.scholar;
const roninAddress = singleData.roninAddress;
const totalSlp = singleData.data.slp.total;
const claimableTotal = singleData.data.slp.claimableTotal;
const lastClaimedItemAt = singleData.data.slp.lastClaimedItemAt;
const todaySoFar = singleData.data.slp.todaySoFar;
const yesterdaySLP = singleData.data.slp.yesterdaySLP;
// const winRate = singleData.data.leaderboard.winRate;
// const winTotal = singleData.data.leaderboard.winTotal;
// const drawTotal = singleData.data.leaderboard.drawTotal;
// const loseTotal = singleData.data.leaderboard.lostTotal;
const elo = singleData.data.leaderboard.elo;
const rank = singleData.data.leaderboard.rank;
const name = singleData.data.leaderboard.name;
const unixTimeStamp = lastClaimedItemAt;
const dateTimeFormat = 'MMMM Do, YYYY h:mm ss A';
const datetime = usertz.datetime(unixTimeStamp, dateTimeFormat);
const newUnixTimeStamp = lastClaimedItemAt + 1209600;
const newdatetime = usertz.datetime(
newUnixTimeStamp,
dateTimeFormat
);
const totalSlpPrice = price * totalSlp;
const finaltotalSlpPrice = totalSlpPrice.toFixed(2);
return (
<Card
style={{
width: '22rem',
backgroundColor: '#4f4f4f',
padding: '20px',
marginTop: '30px',
marginRight: '10px',
}}
key={singleData.id}
>
<Card.Body>
<Card.Title className="text-center">{name}</Card.Title>
Scholar: <span className="font-weight-bold">{myName}</span>
<p className="address">
{' '}
<img src={ronin} alt="ronin" height="20px"></img>{' '}
{roninAddress}
</p>
<Card.Subtitle className="mb-2 text-muted"></Card.Subtitle>
<Row>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
In-Game SLP
<h2>
<span style={{ color: '#3cf0cb' }}>{totalSlp}</span>
<img height="35px" src={slp} alt={slp}></img>
</h2>
<p>USD {finaltotalSlpPrice}</p>
</div>
</Card.Text>
<Card.Text
as={Col}
className="text-center bg-secondary rounded p-2 m-1 d-flex align-items-center justify-content-center"
>
<div>
Claimable SLP
<h2>
<span style={{ color: '#3cf0cb' }}>
{claimableTotal}
<img height="35px" src={slp} alt={slp}></img>
</span>
</h2>
</div>
</Card.Text>
</Row>
Previos Claim: {datetime}
<br />
Next Claim: {newdatetime}
<Card.Text className="bg-dark p-1">
MMR ⚔️ : {elo}
<br />
Rank : {rank}
<br />
SLP Today: {todaySoFar}
<br />
SLP Yesterday: {yesterdaySLP}
<br />
</Card.Text>
<Card.Text className="p-2 bg-dark">
Manager: {manager} % <br />
Scholar: {scholar} %
</Card.Text>
</Card.Body>
</Card>
);
})}
</Row>
</Container>
</Container>
</div>
);
};
export default AxieAPI;
我似乎设法用 localStorage 修复了它。 如果你也遇到这样的可以看看