Atom配置 #

Atom 完整配置 #

jsx
const myAtom = atom({
  key: 'myAtom',
  default: initialValue,
  dangerouslyAllowMutability: false,
  effects: [
    effect1,
    effect2,
  ],
});

配置选项详解 #

key #

key 是 Atom 的唯一标识符,必须全局唯一。

jsx
const countState = atom({
  key: 'countState',
  default: 0,
});

const userCountState = atom({
  key: 'userCountState',
  default: 0,
});

命名建议:

jsx
const [entity][State] = atom({
  key: '[entity][State]',
  default: ...,
});

const todoListState = atom({
  key: 'todoListState',
  default: [],
});

const userSettingsState = atom({
  key: 'userSettingsState',
  default: {},
});

default #

default 定义 Atom 的默认值。

静态值 #

jsx
const countState = atom({
  key: 'countState',
  default: 0,
});

const userState = atom({
  key: 'userState',
  default: {
    name: '',
    email: '',
  },
});

Promise 或异步值 #

jsx
const dataState = atom({
  key: 'dataState',
  default: fetch('/api/data').then(r => r.json()),
});

引用另一个 Atom #

jsx
const baseState = atom({
  key: 'baseState',
  default: 'hello',
});

const derivedState = atom({
  key: 'derivedState',
  default: baseState,
});

dangerouslyAllowMutability #

默认情况下,Recoil 要求状态是不可变的。如果需要直接修改对象,可以设置此选项:

jsx
const mutableState = atom({
  key: 'mutableState',
  default: { count: 0 },
  dangerouslyAllowMutability: true,
});

function Component() {
  const [state, setState] = useRecoilState(mutableState);
  
  const mutate = () => {
    state.count++;
    setState(state);
  };
  
  return <button onClick={mutate}>{state.count}</button>;
}

警告:不推荐使用此选项,可能导致不可预期的行为。

Atom Effects #

Atom Effects 是在 Atom 创建时执行的副作用函数,用于处理副作用。

基本结构 #

jsx
const myAtom = atom({
  key: 'myAtom',
  default: 0,
  effects: [
    (param) => {
      console.log('Atom created:', param.node.key);
      
      return () => {
        console.log('Atom cleanup');
      };
    },
  ],
});

Effects 参数 #

jsx
effects: [
  ({
    node,
    trigger,
    setSelf,
    resetSelf,
    onSet,
    getPromise,
    getLoadable,
    getInfo_UNSTABLE,
  }) => {
    
  },
]
参数 类型 说明
node RecoilState 当前 Atom 的引用
trigger ‘get’ | ‘set’ 触发方式
setSelf function 设置初始值
resetSelf function 重置到默认值
onSet function 监听值变化
getPromise function 异步获取其他状态
getLoadable function 同步获取其他状态

常见使用场景 #

1. 日志记录 #

jsx
const logEffect = ({ node, onSet }) => {
  onSet((newValue, oldValue) => {
    console.log(`[${node.key}]`, oldValue, '->', newValue);
  });
};

const countState = atom({
  key: 'countState',
  default: 0,
  effects: [logEffect],
});

2. 本地存储持久化 #

jsx
const localStorageEffect = (key) => ({ setSelf, onSet }) => {
  const savedValue = localStorage.getItem(key);
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue));
  }
  
  onSet((newValue, _, isReset) => {
    isReset
      ? localStorage.removeItem(key)
      : localStorage.setItem(key, JSON.stringify(newValue));
  });
};

const todoListState = atom({
  key: 'todoListState',
  default: [],
  effects: [localStorageEffect('todos')],
});

3. Session 存储 #

jsx
const sessionStorageEffect = (key) => ({ setSelf, onSet }) => {
  const savedValue = sessionStorage.getItem(key);
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue));
  }
  
  onSet((newValue, _, isReset) => {
    isReset
      ? sessionStorage.removeItem(key)
      : sessionStorage.setItem(key, JSON.stringify(newValue));
  });
};

const formDataState = atom({
  key: 'formDataState',
  default: {},
  effects: [sessionStorageEffect('form_data')],
});

4. 历史记录 #

jsx
const historyEffect = ({ onSet }) => {
  const history = [];
  
  onSet((newValue, oldValue) => {
    history.push({ oldValue, newValue, timestamp: Date.now() });
    console.log('History:', history);
  });
};

const textState = atom({
  key: 'textState',
  default: '',
  effects: [historyEffect],
});

5. 验证 #

jsx
const validationEffect = ({ onSet, setSelf }) => {
  onSet((newValue) => {
    if (newValue < 0) {
      setSelf(0);
      console.warn('Value cannot be negative, reset to 0');
    }
  });
};

const countState = atom({
  key: 'countState',
  default: 0,
  effects: [validationEffect],
});

6. 同步其他状态 #

jsx
const syncEffect = ({ onSet, setSelf, getPromise }) => {
  onSet(async (newValue) => {
    const otherValue = await getPromise(otherState);
    console.log('Other state:', otherValue);
  });
};

7. API 同步 #

jsx
const apiSyncEffect = ({ onSet, setSelf }) => {
  onSet(async (newValue) => {
    try {
      await fetch('/api/save', {
        method: 'POST',
        body: JSON.stringify(newValue),
      });
    } catch (error) {
      console.error('Failed to save:', error);
    }
  });
};

const settingsState = atom({
  key: 'settingsState',
  default: {},
  effects: [apiSyncEffect],
});

组合多个 Effects #

jsx
const userState = atom({
  key: 'userState',
  default: null,
  effects: [
    localStorageEffect('user'),
    logEffect,
    validationEffect,
  ],
});

TypeScript 类型定义 #

基本类型 #

tsx
import { atom } from 'recoil';

const countState = atom<number>({
  key: 'countState',
  default: 0,
});

const textState = atom<string>({
  key: 'textState',
  default: '',
});

对象类型 #

tsx
interface User {
  id: number;
  name: string;
  email: string;
}

const userState = atom<User | null>({
  key: 'userState',
  default: null,
});

数组类型 #

tsx
interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

const todoListState = atom<Todo[]>({
  key: 'todoListState',
  default: [],
});

Effects 类型 #

tsx
import { AtomEffect } from 'recoil';

const localStorageEffect = <T>(key: string): AtomEffect<T> => ({
  setSelf,
  onSet,
}) => {
  const savedValue = localStorage.getItem(key);
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue) as T);
  }
  
  onSet((newValue) => {
    localStorage.setItem(key, JSON.stringify(newValue));
  });
};

const todoListState = atom<Todo[]>({
  key: 'todoListState',
  default: [],
  effects: [localStorageEffect<Todo[]>('todos')],
});

完整示例 #

jsx
import { atom, useRecoilState } from 'recoil';

const localStorageEffect = (key) => ({ setSelf, onSet }) => {
  const savedValue = localStorage.getItem(key);
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue));
  }
  
  onSet((newValue, _, isReset) => {
    isReset
      ? localStorage.removeItem(key)
      : localStorage.setItem(key, JSON.stringify(newValue));
  });
};

const logEffect = ({ node, onSet }) => {
  onSet((newValue, oldValue) => {
    console.log(`[${node.key}]`, { oldValue, newValue });
  });
};

const validationEffect = ({ onSet, setSelf }) => {
  onSet((newValue) => {
    if (newValue.text?.length > 100) {
      setSelf({ ...newValue, text: newValue.text.slice(0, 100) });
    }
  });
};

const noteState = atom({
  key: 'noteState',
  default: {
    id: null,
    text: '',
    createdAt: null,
  },
  effects: [
    localStorageEffect('note'),
    logEffect,
    validationEffect,
  ],
});

function NoteEditor() {
  const [note, setNote] = useRecoilState(noteState);
  
  const handleChange = (e) => {
    setNote({
      ...note,
      text: e.target.value,
      updatedAt: Date.now(),
    });
  };
  
  return (
    <div>
      <textarea
        value={note.text}
        onChange={handleChange}
        maxLength={100}
      />
      <p>{note.text.length}/100</p>
    </div>
  );
}

总结 #

本章学习了 Atom 的高级配置:

配置 说明
key 唯一标识符
default 默认值
dangerouslyAllowMutability 允许直接修改对象
effects 副作用函数数组

下一步,让我们学习 Atom家族,了解如何动态创建多个相关 Atom。

最后更新:2026-03-28