我目前有使用Context和Memo Hooks API的练习代码
这是一个代码段
export const InputContext = createContext()
export const ParentProvider = ({ initialValues, children }) => {
console.log(initialValues)
const [values, setValues ] = useState(initialValues);
const value = {
values,
setValues
}
return <InputContext.Provider value={value}>{children}</InputContext.Provider>
}
我想要的是在单击“编辑”后使用Context API更新包含指标的数组的值。
问题是通过备忘录访问后我无法访问上下文
答案 0 :(得分:1)
使用useContext
,您需要传递整个context
对象(不仅是Consumer
)。像这样使用它
const Component = () =>{
const context = useContext(InputContext)
const { values, setValues } = context
const handleChange = () => setValues('foo')
return(
<>
{values}
<button onClick={handleChange}>Change</button>
</>
)
}
答案 1 :(得分:1)
您需要使用提供程序包装所有需要访问上下文的组件。像这样...
ParentProvider.js
import React, { createContext, useState } from "react";
const INITIAL_STATE = [];
export const InputContext = createContext(INITIAL_STATE);
export const ParentProvider = ({ children }) => {
const [values, setValues] = useState(INITIAL_STATE);
React.useEffect(() => {
console.log("[parentprovider.js]::new values", values);
}, [values]);
return (
<InputContext.Provider value={{ values, setValues }}>
{children}
</InputContext.Provider>
);
};
ShowIndicator.js
import React, { memo, useContext, useState } from "react";
import { Button } from "react-bootstrap";
import { InputContext } from "./ParentProvider";
const ShowIndicator = memo(
({ name, context }) => {
const [_name, _setName] = useState(name);
const [text, setText] = useState();
const { values, setValues } = useContext(InputContext);
const editData = e => {
let newValues = [...values];
newValues[values.indexOf(_name)] = text;
setValues(newValues);
_setName(text);
};
const handleTextChange = e => setText(e.target.value);
const renderDatas = () => {
return (
<div key={_name} className="d-flex justify-content-between">
<input
className="d-flex align-items-center"
defaultValue={_name}
onChange={handleTextChange}
/>
<div>
<Button
variant="info"
style={{ marginRight: "10px" }}
onClick={editData}
>
Edit
</Button>
<Button variant="dark">Delete</Button>
</div>
</div>
);
};
return <div style={{ marginBottom: "5px" }}>{renderDatas()}</div>;
},
(prev, next) => prev.value === next.value
);
export default ShowIndicator;
App.js
import React, { useState, useContext } from "react";
import "./styles.css";
import { Form, Button, Container } from "react-bootstrap";
import ShowIndicator from "./ShowIndicator";
import { InputContext } from "./ParentProvider";
function App() {
const [curText, setCurText] = useState("");
const { values, setValues } = useContext(InputContext);
const onSubmit = e => {
e.preventDefault();
if (!values.includes(curText)) {
values ? setValues([...values, curText]) : setValues([curText]);
setCurText("");
}
};
const onChange = e => setCurText(e.target.value);
return (
<div>
<Container style={{ marginTop: "10px", textAlign: "center" }}>
<div>Add Indicator</div>
<Form inline onSubmit={onSubmit} style={{ marginBottom: "1rem" }}>
<Form.Control
style={{ flex: "1 0 0" }}
onChange={onChange}
value={curText}
/>
<Button type="submit" variant="success">
Submit
</Button>
</Form>
{values &&
values.map((data, index) => {
return <ShowIndicator key={index} name={data} />;
})}
</Container>
</div>
);
}
export default App;
index.js
import React from "react";
import App from "./App";
import { render } from "react-dom";
import { ParentProvider } from "./ParentProvider";
render(
<ParentProvider>
<App />
</ParentProvider>,
document.getElementById("root")
);