繁体   English   中英

从不同的组件设置状态

[英]setting state from a different component

首先,我的方法可能从一开始就被误导了。

我有一个组件列出了由同级组件添加的对象。

我希望在添加新对象时更新列表组件。

如您所见,我在两个组件中调用了相同的函数 (getHostedServiceList)。 显然,这不需要清理,但我想先让它工作

我正在使用钩子来实现这一点。

//输入

const options = [
  { value: '1', label: '1' },
  { value: '2', label: '2' },
  { value: '3', label: '3' },
];

// class Remotes extends Component {
const Remotes = ({ ...props }) => {
  const [service, setService] = useState();
  const [url, setUrl] = useState();
  const [token, setToken] = useState();
  const [displayName, setDisplayName] = useState();
  const [apiUrl, setApiUrl] = useState();
  const [services, setServices] = useState();

  let HOME = process.env.HOME || '';
  if (process.platform === 'win32') {
    HOME = process.env.USERPROFILE || '';
  }

  const getHostedServiceList = () => {
    console.log('props', props);
    if (!fs.existsSync(`${HOME}/providers.json`)) {
      return newMessage(
        `Unable to locate ${HOME}/providers.json`,
        'error',
      );
    }
    const payload = JSON.parse(
      fs.readFileSync(`${HOME}/providers.json`),
    );

    setServices(payload);
  };

  const setProvider = selectedOption => {
    setService(selectedOption.value);
    setUrl(`http://www.${selectedOption.value}.com`);
    setApiUrl(`http://www.${selectedOption.value}.com/api/v1`);
  };

  const { onAddRemote } = props;
  return (
    <div>
      <div>Add a remote host:</div>
      <StyledSelect
        value="Select Provider"
        onChange={setProvider}
        options={options}
      />
      {console.log('service', service)}
      <TextInput
        label="Url"
        defaultValue={url}
        onChange={e => {
          setProvider(e.target.value);
        }}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="API Url"
        defaultValue={apiUrl}
        onChange={e => setApiUrl(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="Token"
        onChange={e => setToken(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="Display Name"
        onChange={e => setDisplayName(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <Button
        disabled={!service || !url || !token}
        onClick={() => {
          onAddRemote({ service, url, apiUrl, token, displayName });
          getHostedServiceList();
        }}
      >
        Add Remote
      </Button>
    </div>
  );
};

//列表


const HostedProviderList = ({ ...props }) => {
  const [services, setServices] = useState();

  let HOME = process.env.HOME || '';
  if (process.platform === 'win32') {
    HOME = process.env.USERPROFILE || '';
  }

  const getHostedServiceList = () => {
    console.log('props', props);
    if (!fs.existsSync(`${HOME}/providers.json`)) {
      return newMessage(
        `Unable to locate ${HOME}/providers.json`,
        'error',
      );
    }
    const payload = JSON.parse(
      fs.readFileSync(`${HOME}/providers.json`),
    );

    setServices(payload);
  };

  useEffect(() => {
    // console.log('props 1', services);
    getHostedServiceList();
  }, []);

  return (
    <Wrapper>
      <Flexbox>
        <Title>Provider List</Title>
      </Flexbox>
      <div>
        {services &&
          services.map((service, i) => (
            <Service key={i}>
              <ServiceName>{service.displayName}</ServiceName>
              <ServiceProvider>{service.service}</ServiceProvider>
            </Service>
          ))}
      </div>
    </Wrapper>
  );
};

我希望在添加新对象时更新列表组件。

这就是ReduxMobX 之类的东西派上用场的地方。 这些工具允许您创建一个“存储”——您可以在该位置加载和存储整个应用程序中不同组件使用的数据。 然后,您将商店连接到与数据交互的各个组件(显示列表、显示创建/编辑表单等)。 每当一个组件修改数据时,所有其他组件都会自动接收更新。

实现这种交叉通信的一种方式是通过发布/订阅机制——每当一个组件创建或修改数据时,它就会发布(或“调度”)一个事件。 其他组件订阅(或“监听”)这些事件并相应地做出反应(或“重新渲染”)。 我将把研究和实现留给读者,因为它无法在 StackOverflow 答案中快速总结。

您也可以尝试新的React hooks ,因为这允许您轻松地在组件之间共享数据。 如果您选择此选项,请特别注意正确操作,因为它很容易偷懒和不负责任。

为了让您开始,这里有一些文章供您阅读。 我强烈推荐阅读第一篇:

是的,您可以使用 Redux(或 React 自己的“上下文”)进行全局状态处理。 但是,要考虑的更简单的解决方案可能只是将数据发送到父级并传递给列表组件,如下所示:

class Parent extends Component {
  state = { objectsAdded: [] }

  onObjectAdded = ( obj ) => {
    // deepclone may be needed
    this.setState({objectsAdded: this.state.objectsAdded.concat(obj)})
  }

  render() {
    return (
      <Fragment>
        <ListComponent objects={this.state.objectsAdded} />
        <ObjectAdder onObjectAdded={this.onObjectAdded} />
      </Fragment>
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM