是否可以在React组件之外更新上下文状态?

时间:2020-05-16 02:44:14

标签: reactjs context-api

在React项目中,存在警报和消息的全局可用上下文。在任何给定的组件中,我都可以使用context.setAlert()编写一条消息。

我有一些提取到实用程序函数中的API提取逻辑。它不是组件。组件在渲染之前以各种方式导入和使用此功能,如下所示:

//MyComponent.js
import {fetchFromApi} from "../util"
import AlertContext from "../contexts/alert"

const MyComponent = () => {
  const alertContext = useContext(AlertContext)
  useEffect(() => 
    fetchFromApi(...)
      .then(() => alertContext.setAlert('All set'), [])
  return <Something/>
}

因此在fetchFromApi中,我希望能够使用该AlertContext.setAlert方法。像这样:

// util.js
export const fetchFromApi = (params) => 
  fetch("...")
    .then(something)
    .then(somethingelse)
    .then(response => {
      // set alert from the AlertContext is what I want to access
      if (response.status === 500) alertContext.setAlert('oh no')
      return response
    })

我不确定是否/如何在组件外部更新上下文状态。这可能吗?

2 个答案:

答案 0 :(得分:0)

修改fetchFromApi的代码,以使其带有带有回调函数的其他参数配置。您可以相应地调用回调。

希望获得帮助。

答案 1 :(得分:0)

您可以更改对象并在上下文提供程序中设置setAlert属性。 fetchApi可以使用此对象。我假设fetchApi仅从Alert上下文中的组件调用,因此可以保证当fetchApi在对象中使用setAlert时将其设置:

const passSetAlert = { setAlert: (x) => x };
const AlertContext = React.createContext();// mutate passSetAlert
function AlertProvider(props) {
  const [alert, setAlert] = React.useState('AA');
  passSetAlert.setAlert = setAlert;
  return (
    <AlertContext.Provider value={{ alert, setAlert }}>
      {props.children}
    </AlertContext.Provider>
  );
}
const fetchFromApi = (message) =>
  setTimeout(() => {
    passSetAlert.setAlert(message);
  }, 2000);

function App() {
  const [count, setCount] = React.useState(0);
  const alertContext = React.useContext(AlertContext);
  const click = () => {
    const newCount = count + 1;
    setCount(newCount);
    fetchFromApi(newCount);
  };
  return (
    <div>
      <button onClick={click}>change alert</button>
      Alert is: {alertContext.alert}
    </div>
  );
}
ReactDOM.render(
  <AlertProvider>
    <App />
  </AlertProvider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>